Streams Replication Practice: Schema Level

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

准备工作...

1. 创建队列

in source database: lo.oracle.com

SQL> show user
USER is "STRMADMIN"
SQL
> begin
2 dbms_streams_adm.set_up_queue
3 ( queue_table => 'capture_queue_table',
4 queue_name => 'capture_queue',
5 queue_user => 'strmadmin');
6 end;
7 /

PL
/SQL procedure successfully completed.

SQL
> select * from capture_queue_table;

no rows selected

in destination database: orcl.oracle.com

SQL> show user
USER is "STRMADMIN"
SQL
> begin
2 dbms_streams_adm.set_up_queue
3 ( queue_table => 'apply_queue_table',
4 queue_name => 'apply_queue',
5 queue_user => 'strmadmin');
6 end;
7 /

PL
/SQL procedure successfully completed.

SQL
> select * from apply_queue_table;

no rows selected

SQL
>

2. LogMiner tablespace Setup  (optional)

in source database: lo.oracle.com

SQL> conn / as sysdba
Connected.
SQL
> create tablespace logmnr_tbs
2 datafile 'E:\oracle\oradata\lo\logmnr_tbs01.dbf'
3 size 25m autoextend on maxsize unlimited;

Tablespace created.

SQL
> begin
2 dbms_logmnr_d.set_tablespace('logmnr_tbs');
3 end;
4 /

PL
/SQL procedure successfully completed.

SQL
>

3. 配置catpure stream (add schema rules) 和propagation rule

in source database: lo.oracle.com

SQL> conn strmadmin/strmadmin
Connected.
SQL
> begin
2 dbms_streams_adm.add_schema_rules
3 (schema_name => 'scott',
4 streams_type => 'capture',
5 streams_name => 'capture_stream',
6 queue_name => 'capture_queue',
7 include_dml => true,
8 include_ddl => true,
9 inclusion_rule => true);
10 end;
11 /

PL
/SQL procedure successfully completed.


SQL
> begin
2 dbms_streams_adm.add_schema_propagation_rules
3 ( schema_name => 'scott',
4 streams_name => 'source_to_target',
5 source_queue_name => 'capture_queue',
6 destination_queue_name => 'apply_queue@orcl.oracle.com',
7 include_dml => true,
8 include_ddl => true,
9 source_database => 'lo.oracle.com');
10 end;
11 /

PL
/SQL procedure successfully completed.



SQL
> select capture_name, status, captured_scn, applied_scn from dba_capture;

CAPTURE_NAME STATUS CAPTURED_SCN APPLIED_SCN
------------------------------ -------- ------------ -----------
CAPTURE_STREAM DISABLED


SQL
> select propagation_name, status from dba_propagation;

PROPAGATION_NAME STATUS
------------------------------ --------
SOURCE_TO_TARGET ENABLED

SQL
> select job, what from dba_jobs;

JOB
----------
WHAT
--------------------------------------------------------------------------------
215
next_date :
= sys.dbms_aqadm.aq$_propaq(job);

21
EMD_MAINTENANCE.EXECUTE_EM_DBMS_JOB_PROCS();


SQL
>

4. 配置apply stream

in destination database: orcl.oracle.com

SQL> begin
2 dbms_streams_adm.add_schema_rules
3 ( schema_name => 'scott',
4 streams_type => 'apply',
5 streams_name => 'apply_stream',
6 queue_name => 'apply_queue',
7 include_dml => true,
8 include_ddl => true,
9 source_database => 'lo.oracle.com');
10 end;
11 /

PL
/SQL procedure successfully completed.

SQL
> select apply_name, status from dba_apply;

APPLY_NAME STATUS
------------------------------ --------
APPLY_STREAM DISABLED

SQL
>

5. 给目标数据库设置instantiation scn.

in source database: lo.oracle.com

SQL> select dbms_flashback.get_system_change_number() from dual;

DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER()
-----------------------------------------
66739793

in destination database: orcl.oracle.com

SQL> begin
2 dbms_apply_adm.set_schema_instantiation_scn
3 ( source_schema_name => 'scott',
4 source_database_name => 'lo.oracle.com',
5 instantiation_scn => 66739793);
6 end;
7 /

PL
/SQL procedure successfully completed.

6.给destination database设置一些参数,使得apply process不会因为出现错误而终止运行

SQL> begin
2 dbms_apply_adm.set_parameter
3 ( apply_name => 'apply_stream',
4 parameter => 'disable_on_error',
5 value => 'n');
6 end;
7 /

PL
/SQL procedure successfully completed.

SQL
> begin
2 dbms_apply_adm.start_apply
3 (apply_name => 'apply_stream');
4 end;
5 /

PL
/SQL procedure successfully completed.

SQL
>

7. 开始capture

 source database: lo.oracle.com

SQL> begin
2 dbms_capture_adm.start_capture
3 (capture_name => 'capture_stream');
4 end;
5 /

PL
/SQL procedure successfully completed.

SQL
>

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

开始测试...

注意到source schema 和destination schema的数据不是完全相同的,如表dept

-- lo.oracle.com

SQL> select * from scott.dept;

DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

-- orcl.oracle.com

SQL> select * from scott.dept;

DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING test
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON


这个时候如果在lo.oracle.com中的scott.dept表进行数据更改的话,orcl.oracle.com并不会跟着改变!!!

SQL> insert into scott.dept values(99, 'test', 'test');

1 row created.

SQL
> commit;

Commit complete.

SQL> select * from scott.dept;

DEPTNO DNAME LOC
---------- -------------- -------------
99 test test
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

-- orcl.oracle.com

SQL> select * from scott.dept;

DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING test
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

但是如果我是新创建对象的话,是可以正常同步的...

-- lo.oracle.com

SQL> create table scott.test as select * from scott.dept;

Table created.

-- orcl.oracle.com

SQL> select * from scott.test;

DEPTNO DNAME LOC
---------- -------------- -------------
99 test test
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

-- lo.oracle.com

SQL> delete from scott.test where deptno=99;

1 row deleted.

SQL
> commit;

-- orcl.oracle.com

SQL> select * from scott.test;

DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

-- lo.oracle.com

SQL> drop table scott.test purge;

Table dropped.

-- orcl.oracle.com

SQL> select * from scott.test;
select * from scott.test
*
ERROR at line
1:
ORA
-00942: table or view does not exist

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

之前做了基于表scott.dept的dml/ddl操作,但是都没有被apply到target的数据库上,说明是出了些问题的,可以通过查询apply_queue_table看一下为什么。

SQL> select q_name, retry_count, sender_name, s.user_data.GetTypeName() as lcr from apply_queue_table s;

Q_NAME RETRY_COUNT SENDER_NAME LCR
------------------------------ ----------- ------------------------------ --------------------------------------------------
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_ROW_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_ROW_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_PROCEDURE_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_DDL_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_ROW_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_ROW_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_ROW_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_ROW_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_ROW_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_DDL_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_PROCEDURE_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_ROW_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_DDL_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_DDL_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_DDL_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_DDL_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_DDL_RECORD
AQ$_APPLY_QUEUE_TABLE_E
0 CAPTURE_STREAM SYS.LCR$_DDL_RECORD

18 rows selected.

而且如果这个时候尝试drop apply stream也会遇到如下的错误....

SQL> exec dbms_apply_adm.drop_apply('apply_stream');
BEGIN dbms_apply_adm.drop_apply(
'apply_stream'); END;
*
ERROR at line
1:
ORA
-26663: error queue for apply process APPLY_STREAM must be empty
ORA
-06512: at "SYS.DBMS_APPLY_ADM_INTERNAL", line 283
ORA
-06512: at "SYS.DBMS_APPLY_ADM_INTERNAL", line 270
ORA
-06512: at "SYS.DBMS_APPLY_ADM", line 691
ORA
-06512: at line 1

可以看出apply_queue_table中有数据,所以无法drop apply stream. 从上面查询结果可以看出,这些数据都存在于apply_queue_table对应的exception queue, 存的都是些错误信息。那么这些错误信息到底是什么呢,oracle online doc 给出了不少方法,参见这里 http://download.oracle.com/docs/cd/B19306_01/server.102/b14229/strms_apmon.htm#i1007852 

最简单的方法是查询视图dba_apply_error

SQL> select error_message from dba_apply_error;

ERROR_MESSAGE
------------------------------------------------------------------------------------------------------------

ORA-
26687: no instantiation SCN provided for "SCOTT"."DEPT" in source database "LO.ORACLE.COM"
ORA-
26687: no instantiation SCN provided for "SCOTT"."DEPT" in source database "LO.ORACLE.COM"
ORA-
00955: name is already used by an existing object
ORA-
00942: table or view does not exist
ORA-
26687: no instantiation SCN provided for "SCOTT"."DEPT" in source database "LO.ORACLE.COM"
ORA-
26687: no instantiation SCN provided for "SCOTT"."DEPT" in source database "LO.ORACLE.COM"
ORA-
26687: no instantiation SCN provided for "SCOTT"."DEPT" in source database "LO.ORACLE.COM"
ORA-
26687: no instantiation SCN provided for "SCOTT"."DEPT" in source database "LO.ORACLE.COM"
ORA-
26687: no instantiation SCN provided for "SCOTT"."DEPT" in source database "LO.ORACLE.COM"
ORA-
26687: no instantiation SCN provided for "SCOTT"."EMP" in source database "LO.ORACLE.COM"
ORA-
26687: no instantiation SCN provided for "SCOTT"."EMP" in source database "LO.ORACLE.COM"

11 rows selected.

另外,我们也可以自己写代码来查询apply_queue_table中的信息, 如下...

SET SERVEROUTPUT ON
DECLARE
v_anydata SYS
.ANYDATA;
v_lcr SYS
.LCR$_ROW_RECORD;
v_row_list SYS
.LCR$_ROW_LIST;
v_result PLS_INTEGER
;
BEGIN

for rec in
(
SELECT user_data
FROM apply_queue_table s
WHERE s
.user_data.GetTypeName() = 'SYS.LCR$_ROW_RECORD'
)
loop

v_anydata :
= rec.user_data;

v_result :
= ANYDATA.GetObject(
self
=> v_anydata,
obj
=> v_lcr);


DBMS_OUTPUT
.PUT_LINE('Command Type : ' || v_lcr.Get_Command_Type);
DBMS_OUTPUT
.PUT_LINE('Object Owner : ' || v_lcr.Get_Object_Owner);
DBMS_OUTPUT
.PUT_LINE('Object Name : ' || v_lcr.Get_Object_Name);
DBMS_OUTPUT
.PUT_LINE('SCN : ' || v_lcr.Get_SCN);
DBMS_OUTPUT
.PUT_LINE('Commit SCN : ' || v_lcr.Get_COMMIT_SCN);
DBMS_OUTPUT
.PUT_LINE('Source Database Name : ' || v_lcr.Get_Source_Database_Name);
DBMS_OUTPUT
.PUT_LINE('-------------------------------------------------------------------------');


end loop;
END;
/

通过这些错误信息,可以分析错误原因,解决之后可以通过dbms_apply_adm.delete_all_errors来删除队列中的错误信息,从而就可以成功drop掉apply stream了。

SQL> exec dbms_apply_adm.drop_apply('apply_stream');  
 BEGIN dbms_apply_adm.drop_apply('apply_stream'); END;  
 *
ERROR at line
1:
ORA
-26663: error queue for apply process APPLY_STREAM must be empty
ORA
-06512: at "SYS.DBMS_APPLY_ADM_INTERNAL", line 283  
ORA-06512: at "SYS.DBMS_APPLY_ADM_INTERNAL", line 270  
ORA-06512: at "SYS.DBMS_APPLY_ADM", line 691  
ORA-06512: at line 1  
 
SQL> exec dbms_apply_adm.delete_all_errors('apply_stream');  
PL/SQL procedure successfully completed.  
SQL> select * from dba_apply_error;  
no rows selected  
SQL> exec dbms_apply_adm.drop_apply('apply_stream');  
PL/SQL procedure successfully completed.  
SQL> exec dbms_aqadm.drop_queue('apply_queue');  
PL/SQL procedure successfully completed.  
SQL> exec dbms_aqadm.drop_queue_table('apply_queue_table');  
PL/SQL procedure successfully completed.  
SQL>

posted @ 2011-03-07 23:22  FangwenYu  阅读(904)  评论(0编辑  收藏  举报