11g新特性:Streams同步捕获

11g中引入了新的Streams特性:Synchronous Capture同步捕获。不同于传统Streams的捕获机制,Synchronous Capture同步捕获不基于归档日志或者在线重做日志来捕捉数据库中的变化。取而代之,同步捕获使用另一种内部机制来捕捉数据库中的变化并对这些捕获的变化实施格式化,最终形成一条LCR(Logical change Record)。这些由同步捕获捕捉到得记录被称为persistent LCRs。同步捕捉总是将记录入列(enqueue)到一个提交时队列中(commit-time queue)以保证事务的顺序准确。

即便我们采用了同步捕捉来替代传统的捕捉方式,propagation和apply并不会有什么不同,这我们无需担忧。

同步捕获可以捕捉由UPDATE、INSERT、DELETE和MERGE四种DML语句产生的DML变化。因为其不依赖于重做和归档的特性,其甚至可以被用在非归档模式下,并且不要求打开任何追加日志。

同步捕捉可能适用于以下几种情景中:

  1. 无法使用基于重做(redo-based)的传统捕获方式(例如在Oracle database Standards Edition中)
  2. 无法使用重做或基于日志挖掘相关的功能,但可以用到其他Streams进程
  3. 要求在用户事务发生的同时执行捕获
  4. 捕获的变化被要求存放在磁盘上的队列中
  5. 克隆较少更新的表上的数据

同步捕获支持对以下数据类型列的DML变更捕捉:

  • VARCHAR2
  • NVARCHAR2
  • NUMBER
  • FLOAT
  • DATE
  • BINARY_FLOAT
  • BINARY_DOUBLE
  • TIMESTAMP
  • TIMESTAMP WITH TIME ZONE
  • TIMESTAMP WITH LOCAL TIME ZONE
  • INTERVAL YEAR TO MONTH
  • INTERVAL DAY TO SECOND
  • RAW
  • CHAR
  • NCHAR
  • UROWID

需要注意的是不同于传统捕获方式,同步捕获不能使用如ADD_SCHEMA_RULES或ADD_GLOBAL_RULES存储过程建立。同步捕获仅能通过ADD_TABLE_RULES建立白名规则(table rule with a positive rule set),而不支持建立黑名规则(negative rule set)。

下面我们通过实例来体验一下该同步捕获新特性。

一、首先我们需要配置Streams所要求的软件环境和前提条件,这包括:

1.确保合理设置Streams相关的初始化参数,可以参考<How to setup Oracle Streams Bi-Directional>一文中Streams推荐的初始化参数的配置

2.在各个数据库中创建Streams管理员用户(一般为strmadmin)

[oracle@rh2 ~]$ export ORACLE_SID=MACLEAN
[oracle@rh2 ~]$ sqlplus  / as sysdba

SQL*Plus: Release 11.2.0.2.0 Production on Wed Apr 6 15:54:51 2011

create user STRMADMIN identified by STRMADMIN
default tablespace USERS
quota unlimited on USERS;

Grant DBA TO STRMADMIN

begin
DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE('STRMADMIN');
end;
/

GRANT SELECT ANY DICTIONARY TO STRMADMIN;
grant insert any table TO STRMADMIN;
grant update any table TO STRMADMIN;
grant delete any table TO STRMADMIN;
grant select any table TO STRMADMIN;
grant alter any table TO STRMADMIN;

grant read on directory data_pump_dir to strmadmin;
grant write on directory data_pump_dir to strmadmin;

3.在源端数据库(source database)以STRMADMIN使用sqlplus登录,并创建以STRMADMIN用户身份连接到目标端数据库中的数据库连接(database link):

SQL> conn strmadmin/STRMADMIN
Connected.

SQL> create database link DW connect to strmadmin identified by STRMADMIN using 'DW';
Database link created.

二、正式开始配置使用同步捕获的Streams
1.进一步确认以上配置的初始化参数、用户权限及数据库连接均已经到位

2.创建示例使用的用户模式以及模式下的示例用表,该步骤在源端和目标端都需要执行:

SQL> create  user user1 identified by user1  default tablespace  users  temporary tablespace temp;
User created.

SQL> grant connect,resource to user1;
Grant succeeded.

SQL> conn user1/user1
Connected.

SQL> create table TAB1(  empid number primary key,  name varchar2(10), comments varchar2(10) );
Table created.

3.以Streams管理员身份登录到源端数据库和目标端数据库中,执行以下创建队列(queue)的操作:

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'strmadmin.sync_queue_table',
queue_name => 'strmadmin.sync_cap_queue',
queue_user => 'user1');
END;
/

4.在目标端数据库中创建apply队列:

BEGIN
 DBMS_STREAMS_ADM.SET_UP_QUEUE(
 queue_table => 'strmadmin.sync_queue_table',
 queue_name => 'strmadmin.sync_apply_queue',
 queue_user => 'user1');
END;
/

5.在目标端数据库创建apply进程,但暂时不启动它:

BEGIN
 DBMS_APPLY_ADM.CREATE_APPLY(
 queue_name => 'strmadmin.sync_apply_queue',
 apply_name => 'sync_apply',
 apply_captured => FALSE);
END;
 /

6.在目标端数据库中为apply进程添加应用规则,该规则要求SYNC_APPLY应用进程将SYNC_APPLY_QUEUE队列中出现的所有DML变更apply到USER1.TAB1表上。

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_RULES(
  table_name => 'user1.tab1',
  streams_type => 'apply',
  streams_name => 'sync_apply',
  queue_name => 'strmadmin.sync_apply_queue',
  source_database => 'MACLEAN');                     /*此处填入源端数据库的global name */
  END;
  /

7.在源端数据库中创建propagation进程将捕获到的变更传播到目标端数据库中。使用ADD_TABLE_PROPAGATION_RULES存储过程创建该 propagation及其白名规则(positive rule set)。在源端数据库中以STRMADMIN身份登录,创建该propagation:

BEGIN
 DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
 table_name => 'user1.tab1',
 streams_name => 'sync_prop',
 source_queue_name => 'strmadmin.sync_cap_queue',
 destination_queue_name => 'strmadmin.sync_apply_queue@DW',          /*@后面跟上连接到目标端数据库的dblink名字 */
 source_database => 'MACLEAN',                            /* 此处填入源端数据库的global name */
 queue_to_queue => TRUE);
END;
/

8.在源端数据库中创建同步捕获进程(synchronous capture),且仅捕捉USER1.TAB1表上的变更:

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_RULES(
  table_name => 'user1.tab1',
  streams_type => 'sync_capture',
  streams_name => 'sync_capture',
  queue_name => 'strmadmin.sync_cap_queue');
END;
/

9.为目标端数据库中的USER1.TAB1表设置实例化SCN号(instantiation SCN):

DECLARE
  iscn NUMBER; -- Variable to hold instantiation SCN value
  BEGIN
  iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
  DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN@DW(            /*@后面跟上连接到目标端数据库的dblink名字*/
  source_object_name => 'USER1.TAB1',
  source_database_name => 'MACLEAN',                                        /* 此处填入源端数据库的global name */
  instantiation_scn => iscn); 
END;

10.在目标端数据库中启动apply:

BEGIN
  DBMS_APPLY_ADM.START_APPLY(
 apply_name => 'sync_apply');
END;
/

因为同步捕获进程会被隐式地启动,所以我们在这里无需去手动启动sync_capture进程。

同时我们无法从dba_capture视图中找到同步捕获进程的信息,因为它们记录在dba_sync_capture视图中:

SQL> set linesize 200 

SQL> select state , capture_name from v$streams_capture;

no rows selected

SQL> select status from dba_capture;

no rows selected

SQL> select capture_name, queue_name, rule_set_name, capture_user
  2  from dba_sync_capture;

CAPTURE_NAME                   QUEUE_NAME                     RULE_SET_NAME                  CAPTURE_USER
------------------------------ ------------------------------ ------------------------------ ------------------------------
SYNC_CAPTURE                   SYNC_CAP_QUEUE                 RULESET$_8                     STRMADMIN

可以通过以下SQL语句了解同步捕获所涉及的表名:

col streams_name for a20
col rule_name for a20

SELECT r.STREAMS_NAME,
       r.RULE_NAME,
       r.SUBSETTING_OPERATION,
       t.TABLE_OWNER,
       t.TABLE_NAME,
       t.ENABLED
  FROM DBA_STREAMS_TABLE_RULES r, DBA_SYNC_CAPTURE_TABLES t
 WHERE r.STREAMS_TYPE = 'SYNC_CAPTURE'
   AND r.TABLE_OWNER = t.TABLE_OWNER
   AND r.TABLE_NAME = t.TABLE_NAME;

STREAMS_NAME         RULE_NAME            SUBSET TABLE_OWNER                    TABLE_NAME                     ENA
-------------------- -------------------- ------ ------------------------------ ------------------------------ ---
SYNC_CAPTURE         TAB17                       USER1                          TAB1                           YES

也可以通过以下SQL语句查询了解那些列上不支持使用同步捕获(synchronous captures):

SELECT OWNER, TABLE_NAME, COLUMN_NAME, SYNC_CAPTURE_REASON
  FROM DBA_STREAMS_COLUMNS
 WHERE SYNC_CAPTURE_VERSION IS NULL;

OWNER                          TABLE_NAME                     COLUMN_NAME                    SYNC_CAPTURE_REASON
------------------------------ ------------------------------ ------------------------------ ---------------------------------------
IX                             AQ$_ORDERS_QUEUETABLE_T        MSGID                          AQ queue table
IX                             AQ$_ORDERS_QUEUETABLE_H        HINT                           AQ queue table
IX                             AQ$_ORDERS_QUEUETABLE_I        HINT                           AQ queue table
IX                             AQ$_ORDERS_QUEUETABLE_I        MSGID                          AQ queue table
IX                             AQ$_ORDERS_QUEUETABLE_I        MSG_LOCAL_ORDER_NO             AQ queue table
IX                             AQ$_STREAMS_QUEUE_TABLE_T      ACTION                         AQ queue table
IX                             AQ$_STREAMS_QUEUE_TABLE_H      NAME                           AQ queue table

11.测试并验证数据复制的情况

SQL> conn user1/user1
Connected.

SQL>  insert into tab1 values(8,'MACLEAN','PERFECT');
1 row created.

SQL> commit;
Commit complete.

/* 连接到目标端数据库并查询TAB1表 */

SQL> conn user1/user1@DW
Connected.

SQL> select * from tab1; 

     EMPID NAME       COMMENTS
---------- ---------- ----------
         8 MACLEAN    PERFECT

12.停止并清理Streams环境;注意以下步骤会将已有的Streams配置移除,因此在执行前应当保证数据库中没有配置其他Streams:
exec dbms_apply_adm.stop_apply('sync_apply');                                   /*目标端数据库 */
exec dbms_capture_adm.drop_capture('sync_capture',true);                   /*源端数据库    */
exec dbms_apply_adm.drop_apply('sync_apply',true);                            /*目标端数据库 */
exec dbms_streams_adm.remove_streams_configuration;                      /* both */

同时删除Streams管理员和示例所用用户模式:
drop user user1 cascade;
drop user strmadmin cascade;

关注dbDao.com的新浪微博

扫码关注dbDao.com 微信公众号:

Comments

  1. wangian says:

    我在参照你的11g新特性:Streams同步捕获和
    配置Streams同步时,配置到在目标端数据库创建apply进程,但暂时不启动它:
    BEGIN
    DBMS_APPLY_ADM.CREATE_APPLY(
    queue_name => ‘strmadmin.sync_apply_queue’,
    apply_name => ‘sync_apply’,
    apply_captured => FALSE);
    END;
    /
    总是出错:
    begin
    *
    ERROR at line 1:
    ORA-26723: user “STRMADMIN” requires the role “DV_STREAMS_ADMIN”
    ORA-06512: at “SYS.DBMS_STREAMS_ADM_UTL_INVOK”, line 349
    ORA-06512: at “SYS.DBMS_STREAMS_ADM”, line 439
    ORA-06512: at “SYS.DBMS_STREAMS_ADM”, line 397
    ORA-06512: at line 2
    参照别处运行
    —以sys用户再登陆后运行—
    BEGIN
    DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE(
    grantee => ‘STRMADMIN’,
    grant_privileges => TURE);
    END;
    /
    后还是出错!请问是什么问题如何解决,急!!!!!!多谢了!请指教。

    • 你好,

      请仔细看 “在各个数据库中创建Streams管理员用户(一般为strmadmin)”部分

      你因该是 有些部分没有执行:

      create user STRMADMIN identified by STRMADMIN
      default tablespace USERS
      quota unlimited on USERS;

      Grant DBA TO STRMADMIN

      begin
      DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE(‘STRMADMIN’);
      end;
      /

      GRANT SELECT ANY DICTIONARY TO STRMADMIN;
      grant insert any table TO STRMADMIN;
      grant update any table TO STRMADMIN;
      grant delete any table TO STRMADMIN;
      grant select any table TO STRMADMIN;
      grant alter any table TO STRMADMIN;

      grant read on directory data_pump_dir to strmadmin;
      grant write on directory data_pump_dir to strmadmin;

Speak Your Mind

TEL/電話+86 13764045638
Email service@parnassusdata.com
QQ 47079569