jinying8869 发表于 2018-9-14 12:09:12

Oracle DG 修改逻辑Standby端数据

  相对物理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>>
  Database>  SQL> EXEC DBMS_LOGSTDBY.SKIP('DML', 'SCOTT', 'DEPT');
  PL/SQL procedure successfully completed.
  SQL>ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;

  Database>  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      NAMEU E PROC
  ----- ------------------------------ ---------- ----- - - ----------
  N   DML                            SCOTT      DEPTY
  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>>
  Database>  执行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>  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>>
  Database>  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>>
  Session>  SQL>CREATE TABLE DAVE AS SELECT * FROM USER_OBJECTS;
  Table created.
  这下可以了,这就是Data Guard的作用。
  注 意: 数据修改完之后,别忘了再次启用Data Guard,以避免不经意的误操作对逻辑Standby的配置造成影响(你说不手动启用Data Guard保护,直接退出行不行,当然也可以,ALTER SESSION所做修改仅对当前会话有效,退出重新登录,原会话设置自然就失效了)。

  SQL>>
  Session>  按照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>>
  Database>  执行完上述语句后,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_STMTINVARCHAR2,
  3    STMT_TYPINVARCHAR2,
  4    SCHEMA    INVARCHAR2,
  5    NAME      INVARCHAR2,
  6    XIDUSN    INNUMBER,
  7    XIDSLT    INNUMBER,
  8    XIDSQN    INNUMBER,
  9    ACTION    OUT NUMBER,
  10    NEW_STMTOUT VARCHAR2
  11) AS
  12BEGIN
  13
  14    NEW_STMT := REPLACE(OLD_STMT, '/u01/oradata/orcl_pd/', '/u01/oradata/orcl_st');
  15    ACTION := DBMS_LOGSTDBY.SKIP_ACTION_REPLACE;
  16
  17EXCEPTION
  18    WHEN OTHERS THEN
  19      ACTION := DBMS_LOGSTDBY.SKIP_ACTION_ERROR;
  20      NEW_STMT := NULL;
  21END HANDLE_TBS_DDL;
  22/
  Procedure created.
  逻辑非常简单,基本上就是一个REPLACE,不过PROCEDURE中声明的变量看起来很多,这个是固定格式,不建议修改。
  停止逻辑Standby的SQL应用:

  SQL>>
  Database>  如果不停,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>>
  Database>  测试一下,在Primary端创建一个新的表空间:

  SQL> CREATE TABLESPACE BOOKS DATAFILE '/u01/oradata/orcl_pd/books01.dbf'>  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'>  LOGSTDBY status: ORA-16110: 逻辑备用应用 DDL 的用户过程处理

  LOGSTDBY>  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'>  LOGSTDBY status: ORA-16202: 跳过过程已请求替换语句

  LOGSTDBY>  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'>
  Completed: create tablespace books datafile '/u01/oradata/orcl_st/books01.dbf'>
  LOGSTDBY stmt: create tablespace books datafile '/u01/oradata/orcl_st/books01.dbf'>  LOGSTDBY status: ORA-16204: 成功应用了 DDL
  oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html

页: [1]
查看完整版本: Oracle DG 修改逻辑Standby端数据