相对物理Standby,逻辑Standby的管理要复杂一点点。这个就是管理一个半数据库和管理两个数据库的差异(假设Data Guard环境为一主一备的情况下),毕竟逻辑Standby只是逻辑上,仿佛与Primary数据库一致,其实它是一个独立运行的,甚至可能与Primary数据库完全不同的数据库系统,对于这种配置环境,管理上多花点工夫想想也是应该的。


1、指定对象跳过应用


在默认情况下,接收自Primary的REDO数据中,所有能够被逻辑Standby数据库支持的操作都会在逻辑Standby端执行。如果你希望跳过对某些对象的某些操作的话,DBMS_LOGSTDBY.SKIP就能派上用场了。


先来看看DBMS_LOGSTDBY.SKIP的语法:


DBMS_LOGSTDBY.SKIP (


stmt                       IN VARCHAR2,


schema_name                IN VARCHAR2 DEFAULT NULL,


object_name                IN VARCHAR2 DEFAULT NULL,


proc_name                  IN VARCHAR2 DEFAULT NULL,


use_like                   IN BOOLEAN DEFAULT TRUE,


esc                        IN CHAR1 DEFAULT NULL);


除stmt外,其他都是可选参数,并且看字面意义就能明白其所指。例如,你想跳过SCOTT用户下对dept表的DML操作,可以通过执行下列语句实现(执行该过程前需要先停止REDO应用):


SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;


Database altered.


SQL> EXEC DBMS_LOGSTDBY.SKIP('DML', 'SCOTT', 'DEPT');


PL/SQL procedure successfully completed.


SQL>ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;


Database altered.



2、恢复对象同步


如果逻辑Standby中的某些表取消了与Primary的同步维护,现在希望再恢复同步,没问题,DBMS_LOGSTDBY家大业大,它还有个叫UNSKIP的门生专干这个。


我们来看一下DBMS_LOGSTDBY.UNSKIP的语法:


DBMS_LOGSTDBY.UNSKIP (


stmt                   IN VARCHAR2,


schema_name            IN VARCHAR2,


object_name                IN VARCHAR2);


三项均为必选参数,各参数的定义与SKIP过程相同。


下面演示恢复tmp1表的同步。


首先查看当前逻辑Standby都有哪些对象处于不同步状态,可以通过DBA_LOGSTDBY_SKIP视图查看,例如:


SQL> select * from dba_logstdby_skip;


ERROR STATEMENT_OPT                  OWNER      NAME  U E PROC


----- ------------------------------ ---------- ----- - - ----------


N     DML                            SCOTT      DEPT  Y


N     INTERNAL SCHEMA                SYSTEM     %     Y


N     INTERNAL SCHEMA                SYS        %     Y


N     INTERNAL SCHEMA                OLAPSYS    %     Y


N     INTERNAL SCHEMA                SI_INFORMT %     Y


N     INTERNAL SCHEMA                MGMT_VIEW  %     Y


N     INTERNAL SCHEMA                ORDPLUGINS %     Y


N     INTERNAL SCHEMA                XDB        %     Y


N     INTERNAL SCHEMA                SYSMAN     %     Y


N     INTERNAL SCHEMA                WMSYS      %     Y


N     INTERNAL SCHEMA                DBSNMP     %     Y


注意在执行DBMS_LOGSTDBY.UNSKIP过程前,要停止当前的SQL应用状态:


SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;


Database altered.


执行DBMS_LOGSTDBY.UNSKIP过程,恢复前面停止的scott.tmp1表的应用:


SQL> execute dbms_logstdby.unskip('DML', 'SCOTT', 'dept');


PL/SQL procedure successfully completed.



3、添加或重建对象


指定对象跳过应用虽然被取消,但是有可能在此期间由于Primary数据库做过数据修改,两端此时已经不同步,如果Standby端继续应用极有可能导致应用错误的数据。


对于这类情况,Oracle也早有预见,DBMS_LOGSTDBY包中还有一个过程叫INSTANTIATE_TABLE,专门用来同步一下跳过的对象,以保持与Primary数据库的一致。


DBMS_LOGSTDBY.INSTANTIATE_TABLE的调用语法如下:


DBMS_LOGSTDBY.INSTANTIATE_TABLE (


schema_name            IN VARCHAR2,


table_name             IN VARCHAR2,


dblink                 IN VARCHAR2);


除了SCHEMA名称和表名称外,还需要提供一个数据库链,因此这里我们首先在逻辑Standby端创建一个连接Primary数据库的数据库链:


SQL> CREATE DATABASE LINK PRE_TBL_DATA CONNECT TO SYSTEM IDENTIFIED BY ADMIN


USING 'ORCL_PD';


Database link created.


执行使用DBMS_LOGSTDBY.INSTANTIATE_TABLE过程,重新同步SCOTT.TMP1表(注意执行该过程前别忘了暂停当前的SQL应用):


SQL>EXEC DBMS_LOGSTDBY.INSTANTIATE_TABLE('SCOTT', 'DEPT', 'PRE_TBL_DATA');


PL/SQL procedure successfully completed.


SQL> SELECT * FROM SCOTT.DEPT;


对象已被重建,然后重新启动SQL应用即可:


SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;


Database altered.



4、逻辑Standby端修改数据


逻辑Standby的一个极具实用价值的特性就是可以边查询边应用,因此将其作为报表服务器专供查询是个很不错的想法,而且逻辑Standby相对于物理Standby而言更具灵活性,如我们可以在逻辑Standby上,对一些表创建Primary数据库并不方便创建的索引、约束,甚至可以做DML/DDL操作(当然,需要注意不要破坏了与Primary数据库之间同步的逻辑关系)。


不过由于此时Data Guard仍然控制着对逻辑Standby数据库中表的读写操作,因此,如果你想对逻辑Standby中的数据做些什么的话,ALTER SESSION DISABLE|ENABLE GUARD语句就必须牢记在心了,它拥有像"芝麻开门"一样神奇的能力。 下面我们就来感受一下吧。


在逻辑Standby端启动SQL应用的情况下,执行DDL操作:


SQL> GRANT DBA TO SCOTT;


Grant succeeded.


SQL> CONN SCOTT/TIGER;


Connected.


SQL> CREATE TABLE DAVE AS SELECT * FROM USER_OBJECTS;


CREATE TABLE DAVE AS SELECT * FROM USER_OBJECTS


*


ERROR at line 1:


ORA-01031: insufficient privileges


出错了,提示权限不足,实际上SCOTT被授予了DBA角色,肯定拥有CREATE TABLE权限的,因此此处与用户的权限无关,而是有其他因素制约了SCOTT无法进行修改。


下面禁用Data Guard保护之后,再次尝试操作数据:


SQL> ALTER SESSION DISABLE GUARD;


Session altered.


SQL>  CREATE TABLE DAVE AS SELECT * FROM USER_OBJECTS;


Table created.


这下可以了,这就是Data Guard的作用。


注 意: 数据修改完之后,别忘了再次启用Data Guard,以避免不经意的误操作对逻辑Standby的配置造成影响(你说不手动启用Data Guard保护,直接退出行不行,当然也可以,ALTER SESSION所做修改仅对当前会话有效,退出重新登录,原会话设置自然就失效了)。


SQL> ALTER SESSION ENABLE GUARD;


Session altered.


按照Oracle的建议,还是尽可能不要在逻辑Standby端执行DML之类操作,以免破解其与Primary之间同步的逻辑关系,


也可以通过下列语句查看当前数据库是否处于Data Guard保护状态:


SQL> SELECT GUARD_STATUS FROM V$DATABASE;


GUARD_S


-------


ALL


该参数对应三个值:


ALL:表示对数据库中所有对象启动修改保护,除SYS用户外,其他用户均不能直接修改数据。


STANDBY:表示对处于逻辑Standby维护关系的对象启动修改保护,除SYS用户外,其他用户均不能直接修改数据。


NONE:不启动数据保护。


如果要永久设置数据库的Data Guard保护模式,则是通过ALTER DATABASE命令来完成,可指定的值也正是上述的三种,例如:


SQL> ALTER DATABASE GUARD STANDBY;


Database altered.


执行完上述语句后,Data Guard仅对处于逻辑Standby维护关系的对象进行防止修改操作的保护。


考虑到逻辑Standby中也有可能对数据进行修改(正如上例演示),因此这里引申谈一谈在逻辑Standby数据库中,约束和触发器的执行模式。默认情况下,约束和触发器都能在逻辑Standby端正常运行。约束和触发器在逻辑Standby端的执行可以分成两种情况:


对于SQL应用维护的约束和触发器,由于在Primary数据库已经检查过约束,因此Standby端不需要再次检查;触发器的情况也是这样,Primary端操作时结果已经被记录,因此逻辑Standby端将直接被应用,而不会二次触发。


对于没有SQL应用维护的约束和触发器,其执行情况与普通的Oracle数据库环境相同。



5、重定义REDO应用执行的操作


对于逻辑Standby数据库,你甚至可以通过编写自定义的PROCEDURE,来重新定义SQL应用时执行的操作。


如逻辑Standby数据库的文件路径与Primary数据库路径不同,如果是物理Standby,可以通过*_FILE_NAME_CONVERT之类的参数处理,在逻辑Standby环境中这几个参数无效,应该如何处理呢?答案就是通过编写自定义的过程,修改SQL应用时执行的操作。


下面通过示例,演示通过编写自定义的PROCEDURE,修改创建表空间时逻辑Standby端数据文件的路径。


首先当然是创建一个过程,建议创建在SYS下,因为在这个用户下的操作肯定不会有同步的问题,如下所示:


SQL> CREATE OR REPLACE PROCEDURE SYS.HANDLE_TBS_DDL (


2    OLD_STMT  IN  VARCHAR2,


3    STMT_TYP  IN  VARCHAR2,


4    SCHEMA    IN  VARCHAR2,


5    NAME      IN  VARCHAR2,


6    XIDUSN    IN  NUMBER,


7    XIDSLT    IN  NUMBER,


8    XIDSQN    IN  NUMBER,


9    ACTION    OUT NUMBER,


10    NEW_STMT  OUT VARCHAR2


11  ) AS


12  BEGIN


13


14    NEW_STMT := REPLACE(OLD_STMT, '/u01/oradata/orcl_pd/', '/u01/oradata/orcl_st');


15    ACTION := DBMS_LOGSTDBY.SKIP_ACTION_REPLACE;


16


17  EXCEPTION


18    WHEN OTHERS THEN


19      ACTION := DBMS_LOGSTDBY.SKIP_ACTION_ERROR;


20      NEW_STMT := NULL;


21  END HANDLE_TBS_DDL;


22  /


Procedure created.


逻辑非常简单,基本上就是一个REPLACE,不过PROCEDURE中声明的变量看起来很多,这个是固定格式,不建议修改。


停止逻辑Standby的SQL应用:


SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;


Database altered.


如果不停,PROCEDURE不能生效。


执行DBMS_LOGSTDBY.SKIP过程,将编写的过程注册到表空间处理的SQL应用中:


SQL> EXEC DBMS_LOGSTDBY.SKIP (stmt => 'TABLESPACE',proc_name => 'sys.handle_tbs_ddl');


PL/SQL procedure successfully completed.


这里也要借助DBMS_LOGSTDBY.SKIP过程实现。该过程功能非常强大,而且操作非常灵活。


重启SQL应用:


SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;


Database altered.


测试一下,在Primary端创建一个新的表空间:


SQL> CREATE TABLESPACE BOOKS DATAFILE '/u01/oradata/orcl_pd/books01.dbf' SIZE 20m;


Tablespace created.


SQL> SELECT FILE_NAME FROM DBA_DATA_FILES WHERE TABLESPACE_NAME='BOOKS';


FILE_NAME


-----------------------------------------------------------------------------


/u01/oradata/orcl_pd/books01.dbf


转向逻辑Standby数据库查看:


SQL> SELECT FILE_NAME FROM DBA_DATA_FILES WHERE TABLESPACE_NAME='BOOKS';


FILE_NAME


----------------------------------------------------------------------------


/u01/oradata/orcl_st/books01.dbf


表空间成功创建,并且数据文件路径也被转换为我们指定的路径。


此时如果你查看Alert日志文件,会发现其中记录下了类似这样的信息:


LOGSTDBY stmt: create tablespace books datafile '/u01/oradata/orcl_pd/books01.dbf' size 20m


LOGSTDBY status: ORA-16110: 逻辑备用应用 DDL 的用户过程处理


LOGSTDBY id: XID 0x0001.009.000000d1, hSCN 0x0000.0012ec41,


lSCN 0x0000.0012ec41, Thread 1, RBA 0x007f.0000079a.80,


txnCscn 0x0000.0012ec43, PID 5816, ORACLE.EXE (P004)


LOGSTDBY stmt: create tablespace books datafile '/u01/oradata/orcl_st/books01.dbf' size 20m


LOGSTDBY status: ORA-16202: 跳过过程已请求替换语句


LOGSTDBY id: XID 0x0001.009.000000d1, hSCN 0x0000.0012ec41,


lSCN 0x0000.0012ec41, Thread 1, RBA 0x007f.0000079a.80,


txnCscn 0x0000.0012ec43, PID 5816, ORACLE.EXE (P004)


create tablespace books datafile '/u01/oradata/orcl_st/books01.dbf' size 20m


Completed: create tablespace books datafile '/u01/oradata/orcl_st/books01.dbf' size 20m


LOGSTDBY stmt: create tablespace books datafile '/u01/oradata/orcl_st/books01.dbf' size 20m


LOGSTDBY status: ORA-16204: 成功应用了 DDL


oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html