Oracle流複製技術

llnnmc發表於2017-04-19

Oracle流複製是結合日誌挖掘、佇列等技術,實現多資料庫、異構、遠端等環境下資料同步的一種實現方式。主要被用於靈活的複製和容災解決方案。


Oracle流複製相比較其他資料庫同步方式,如Dataguard、Advanced Replication,流複製擁有以下幾點顯著的優勢:

1、靈活的複製策略:可以分別針對資料庫、模式、表等不同級別設定複製策略,相比Dataguard必須整個資料庫複製而言,可以節省相當的資源。

2、高可用性:在異構環境下(不同的作業系統),Dataguard無法使用,流複製可以充分利用現有的裝置與技術。

3、對網路條件的輕度依賴:流複製的傳播是經過logmnr挖掘幷包裝的邏輯變更記錄(LCRs),相比Dataguard傳送archived redo log、Advanced Replication的mview log與mview重新整理的方式,流複製對網路的需求降低了很多。

4、實時性:由監控程式負責實時監控使用者操作反應在log當中的記錄並傳遞給目標資料庫進行接收,然後轉換為實際的操作同步目標資料庫,並可根據實際情況調整同步的間隔。

5、對主資料庫效能的低影響:相對於其他複製方式,流複製基於對log物理檔案進行分析等動作完成,只佔用極少部分資源,並且無論流複製執行成功與否,都不會影響到主庫的正常使用。


流複製中,源庫必須設定為歸檔模式,如果是雙向複製,則源庫和目標庫都要置於歸檔模式。


以下給出一個在生產環境中的具體例子來說明流複製技術的運用方法。這裡的需求是主伺服器資料庫的一個名為CMES的模式,包括其表、索引、儲存過程程式碼等物件結構和資料的變更都要求能同步到本地節點的資料庫中。


一、搭建流複製環境


1、本地節點的流複製環境搭建


conn / as sysdba


修改例項引數

alter system set global_names=true;

alter system set aq_tm_processes=1;


建立streams表空間

create tablespace streams datafile 'd:\oradata\mes\streams01.dbf' size 200m;


logminer 的資料字典從system表空間轉移到streams表空間

execute dbms_logmnr_d.set_tablespace('streams');


建立strmadmin使用者並授權

create user strmadmin identified by strmadmin default tablespace streams quota unlimited on streams;

grant connect, resource, dba, aq_administrator_role to strmadmin;

begin

    dbms_streams_auth.grant_admin_privilege(grantee          => 'strmadmin',

                                            grant_privileges => true);

end;

/


tnsnames.ora中新增服務名,指向主伺服器端

mes_0 =

  (DESCRIPTION =

    (ADDRESS_LIST =

      (ADDRESS = (PROTOCOL = TCP)(HOST = ora11g-1)(PORT = 1521))

    )

    (CONNECT_DATA =

      (SERVICE_NAME = mes)

    )

  )


建立指向主伺服器端的資料庫連結

create public database link dl_mes_0 connect to system identified by mesHz2 using 'mes_0';


測試透過資料庫連結可以訪問到對方主機

select host_name from v$instance@dl_mes_0;


HOST_NAME

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

ORA11G-1


建立與資料庫連結訪問同名的global_name

第一個本地節點可命名為dl_mes_1,第二個本地節點可命令為dl_mes_2,以此類推

alter database rename global_name to dl_mes_1;


建立流佇列

conn strmadmin/strmadmin

exec dbms_streams_adm.set_up_queue();


建立應用程式

conn strmadmin/strmadmin

begin

    dbms_streams_adm.add_schema_rules(schema_name     => 'cmes',

                                      streams_type    => 'apply',

                                      streams_name    => 'apply_streams',

                                      queue_name      => 'strmadmin.streams_queue',

                                      include_dml     => true,

                                      include_ddl     => true,

                                      source_database => 'dl_mes_0',

                                      inclusion_rule  => true);

end;

/


2、主伺服器端的流複製環境搭建


conn / as sysdba


開啟補充日誌

alter database add supplemental log data;


修改例項引數

alter system set global_names=true;

alter system set aq_tm_processes=1;

alter system set open_links=10 scope=spfile;

alter system set open_links_per_instance=10 scope=spfile;


建立streams表空間

create tablespace streams datafile 'd:\oradata\mes\streams01.dbf' size 200m;


logminer的資料字典從系統表空間轉移到streams表空間

execute dbms_logmnr_d.set_tablespace('streams');


建立strmadmin使用者並授權

create user strmadmin identified by strmadmin default tablespace streams quota unlimited on streams;

grant connect, resource, dba, aq_administrator_role to strmadmin;

begin

    dbms_streams_auth.grant_admin_privilege(grantee          => 'strmadmin',

                                            grant_privileges => true);

end;

/


tnsnames.ora中新增指向各個本地節點的網路服務名

第一個本地節點可命名為mes_1,第二個本地節點可命令為mes_2,以此類推,各節點計算機名對應為oraxe11g-1oraxe11g-2

mes_1 =

  (DESCRIPTION =

    (ADDRESS_LIST =

      (ADDRESS = (PROTOCOL = TCP)(HOST = oraxe11g-1)(PORT = 1521))

    )

    (CONNECT_DATA =

      (SERVICE_NAME = mes)

    )

  )


建立資料庫連結

對應各個本地節點的網路服務名來建立,如dl_mes_1對應mes_1dl_mes_2對應mes_2

create public database link dl_mes_1 connect to system identified by mesHz2 using 'mes_1';


測試透過資料庫連結dl_mes_1dl_mes_2等可以分別訪問到各個節點

select host_name from v$instance@dl_mes_1;


HOST_NAME

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

ORAXE11G-1


建立與資料庫連結訪問同名的global_name

alter database rename global_name to dl_mes_0;


建立流佇列

conn strmadmin/strmadmin

exec dbms_streams_adm.set_up_queue();


建立捕獲程式

conn strmadmin/strmadmin

begin

    dbms_streams_adm.add_schema_rules(schema_name    => 'cmes',

                                      streams_type   => 'capture',

                                      streams_name   => 'capture_streams',

                                      queue_name     => 'strmadmin.streams_queue',

                                      include_dml    => true,

                                      include_ddl    => true,

                                      inclusion_rule => true);

end;

/


建立傳播程式

conn strmadmin/strmadmin

begin

    dbms_streams_adm.add_schema_propagation_rules(schema_name            => 'cmes',

                                                  streams_name           => 'main_to_node1',

                                                  source_queue_name      => 'strmadmin.streams_queue',

                                                  destination_queue_name => 'strmadmin.streams_queue@dl_mes_1',

                                                  include_dml            => true,

                                                  include_ddl            => true,

                                                  source_database        => 'dl_mes_0',

                                                  inclusion_rule         => true,

                                                  queue_to_queue         => true);

end;

/


當需要建立多個傳播程式向不同節點發布時,需要指定不同的stream_namedestination_queue_name,如以下建立指向第二個本地節點的傳播程式

conn strmadmin/strmadmin

begin

    dbms_streams_adm.add_schema_propagation_rules(schema_name            => 'cmes',

                                                  streams_name           => 'main_to_node2',

                                                  source_queue_name      => 'strmadmin.streams_queue',

                                                  destination_queue_name => 'strmadmin.streams_queue@dl_mes_2',

                                                  include_dml            => true,

                                                  include_ddl            => true,

                                                  source_database        => 'dl_mes_0',

                                                  inclusion_rule         => true,

                                                  queue_to_queue         => true);

end;

/


3、例項化本地節點


根據具體業務,利用資料泵進行匯入。這裡具體業務是需要建立幾個自己的表空間和使用者模式,並從主伺服器上匯入模式資料到本地。


conn / as sysdba


建立表空間

create tablespace cmes datafile 'd:\oradata\mes\cmes01.dbf' size 100m;

create tablespace rmes datafile 'd:\oradata\mes\rmes01.dbf' size 2g;

create tablespace indx datafile 'd:\oradata\mes\indx01.dbf' size 2g;

create tablespace hmes datafile 'd:\oradata\mes\hmes01.dbf' size 2g;


建立RMESBOSCHABS使用者並授權

create user rmes identified by rmes default tablespace rmes;

create user bosch identified by huizhong default tablespace rmes;

create user abs identified by huizhong default tablespace rmes;

grant connect,resource to rmes,bosch,abs;


匯入主伺服器端的CMES模式基礎資料

$impdp strmadmin/strmadmin network_link=dl_mes_0 schemas=cmes


匯入主伺服器端的RMESBOSCHABS模式後設資料

$impdp strmadmin/strmadmin network_link=dl_mes_0 schemas=rmes,bosch,abs content=metadata_only


編譯無效物件

@?/rdbms/admin/utlrp


4、啟動流複製程式


本地節點啟動應用程式

conn strmadmin/strmadmin

exec dbms_apply_adm.start_apply('apply_streams');


主伺服器端啟動捕獲程式

conn strmadmin/strmadmin

exec dbms_capture_adm.start_capture('capture_streams');


檢查主伺服器端警告日誌,確認日誌捕獲的啟動

Fri Apr 14 16:47:04 2017

LOGMINER: Begin mining logfile for session 1 thread 1 sequence 40, E:\ARCHIVELOG\MES\ARC_78AE6A4D_1_941117583_40.LOG

Fri Apr 14 16:47:05 2017

LOGMINER: End mining logfile: E:\ARCHIVELOG\MES\ARC_78AE6A4D_1_941117583_40.LOG

Fri Apr 14 16:47:05 2017

LOGMINER: Begin mining logfile for session 1 thread 1 sequence 41, D:\ORADATA\MES\REDO02.LOG

Fri Apr 14 16:47:14 2017

LOGMINER: End mining logfile: D:\ORADATA\MES\REDO02.LOG

Fri Apr 14 16:47:14 2017

LOGMINER: Begin mining logfile for session 1 thread 1 sequence 42, D:\ORADATA\MES\REDO03.LOG


檢查本地節點警告日誌,確認日誌應用的啟動

Fri Apr 14 16:46:41 2017

Streams APPLY AP01 for APPLY_STREAMS started with pid=24, OS id=3144

Fri Apr 14 16:46:42 2017

Streams Apply Server for APPLY_STREAMS started AS02 with pid=31 OS id=1768

Fri Apr 14 16:46:42 2017

Streams Apply Server for APPLY_STREAMS started AS03 with pid=32 OS id=2484

Fri Apr 14 16:46:42 2017

Streams Apply Reader for APPLY_STREAMS started AS01 with pid=29 OS id=4040

Fri Apr 14 16:46:42 2017

Streams Apply Server for APPLY_STREAMS started AS04 with pid=35 OS id=756

Fri Apr 14 16:46:42 2017

Streams Apply Server for APPLY_STREAMS started AS05 with pid=36 OS id=740


5、流複製功能驗證


測試主伺服器端資料庫CMES模式的更新,是否能夠自動同步到本地節點,包括DMLDDL操作。如未能同步,則檢查主伺服器端和本地節點的警告日誌資訊,排查出錯原因。


表資料更新

select * from cmes.c_emp_t;

update cmes.c_emp_t t set t.emp_password = '111111' where t.emp_no = 'TEST';

commit;


增加表

create table cmes.c_emp1_t as select * from cmes.c_emp_t;

select * from cmes.c_emp1_t;


修改表結構

alter table cmes.c_emp1_t add remark varchar2(20);

update cmes.c_emp1_t t set t.remark = 'test' where t.emp_no = 'TEST';

commit;

desc cmes.c_emp1_t;


增加索引

create index cmes.idx_emp1_remark on cmes.c_emp1_t(remark) tablespace indx;

select table_name, index_name, index_type, status, tablespace_name from dba_indexes where owner='CMES' and table_name='C_EMP1_T';


刪除索引

drop index cmes.idx_emp1_remark;

select table_name, index_name, index_type, status, tablespace_name from dba_indexes where owner='CMES' and table_name='C_EMP1_T';


刪除表

drop table cmes.c_emp1_t purge;

select * from cmes.c_emp1_t;


新增儲存過程

create or replace procedure cmes.my_test(res out varchar2) as

begin

    res := 'OK';

end;

/


更新儲存過程

create or replace procedure cmes.my_test(res out varchar2) as

begin

    res := 'NOK';

end;

/


刪除儲存過程

drop procedure cmes.my_test;


6、建立流複製心跳


為監視流複製的工作狀態,在主伺服器上建立心跳錶

create table cmes.streams_hb(hb_name varchar2(20), hb_time varchar2(20)) tablespace cmes;


插入資料

insert into cmes.streams_hb values('dl_mes_0', to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'));

commit;


建立排程作業,設定為每分鐘更新一次心跳時間

conn strmadmin/strmadmin

begin

    dbms_scheduler.create_job(job_name        => 'strmadmin.job_streams_hb',

                              job_type        => 'plsql_block',

                              job_action      => 'update cmes.streams_hb set hb_time = to_char(sysdate, ''yyyy-mm-dd hh24:mi:ss'') where hb_name = ''dl_mes_0'';',

                              start_date      => sysdate,

                              repeat_interval => 'freq = minutely; interval = 1',

                              enabled         => true,

                              auto_drop       => false);

end;

/


觀察本地節點的心跳錶資料是否按心跳時間同步更新

select * from cmes.streams_hb;


HB_NAME              HB_TIME

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

dl_mes_0             2017-05-09 12:19:47


二、針對表級別的配置說明


如果流複製定義在表級別,則幾個程式的建立可採用如下形式。


主伺服器端建立表級別的傳播程式

begin

    dbms_streams_adm.add_table_propagation_rules(table_name             => 'scott.emp',

                                                 streams_name           => 'scott_emp_main_to_node1',

                                                 source_queue_name      => 'strmadmin.streams_queue',

                                                 destination_queue_name => 'strmadmin.streams_queue@dl_mes_1',

                                                 include_dml            => true,

                                                 include_ddl            => true,

                                                 source_database        => 'dl_mes_0',

                                                 inclusion_rule         => true,

                                                 queue_to_queue         => true);

end;

/


主伺服器端建立表級別的捕獲程式

begin

    dbms_streams_adm.add_table_rules(table_name     => 'scott.emp',

                                     streams_type   => 'capture',

                                     streams_name   => 'scott_emp_capture_streams',

                                     queue_name     => 'strmadmin.streams_queue',

                                     include_dml    => true,

                                     include_ddl    => true,

                                     inclusion_rule => true);

end;

/


本地節點建立表級別的應用程式

begin

    dbms_streams_adm.add_table_rules(table_name      => 'scott.emp',

                                     streams_type    => 'apply',

                                     streams_name    => 'scott_emp_apply_streams',

                                     queue_name      => 'strmadmin.streams_queue',

                                     include_dml     => true,

                                     include_ddl     => true,

                                     source_database => 'dl_mes_0',

                                     inclusion_rule  => true);

end;

/


本地節點的例項化

本地節點匯入主伺服器端的表

$impdp strmadmin/strmadmin network_link=dl_mes_0 schemas=scott include=table:"in('EMP')" table_exists_action=replace


三、流複製配置的刪除


停止應用程式

conn strmadmin/strmadmin

exec dbms_apply_adm.stop_apply(apply_name => 'apply_streams');


刪除應用程式

conn strmadmin/strmadmin

begin

  dbms_apply_adm.drop_apply(apply_name            => 'apply_streams',

                            drop_unused_rule_sets => true);

end;

/


如果刪除應用程式時報錯應用程式的錯誤佇列必須為空,則需要先刪除之前應用程式所有的錯誤資訊,然後再執行刪除程式的操作

conn strmadmin/strmadmin

select * from dba_apply_error;

exec dbms_apply_adm.delete_all_errors(apply_name=>'apply_streams');


停止捕獲程式

conn strmadmin/strmadmin

begin

  dbms_capture_adm.stop_capture(capture_name => 'capture_streams',

                                force        => true);

end;

/


刪除捕獲程式

conn strmadmin/strmadmin

begin

  dbms_capture_adm.drop_capture(capture_name          => 'capture_streams',

                                drop_unused_rule_sets => true);

end;

/


停止傳播程式

conn strmadmin/strmadmin

begin

  dbms_propagation_adm.stop_propagation(propagation_name => 'main_to_node1',

                                        force            => true);

end;

/


刪除傳播程式

conn strmadmin/strmadmin

begin

  dbms_propagation_adm.drop_propagation(propagation_name      => 'main_to_node1',

                                        drop_unused_rule_sets => true);

end;

/


刪除主伺服器端和本地節點的佇列及佇列表

conn strmadmin/strmadmin

begin

dbms_streams_adm.remove_queue(queue_name              => 'STREAMS_QUEUE',

                              cascade                 => true,

                              drop_unused_queue_table => true);

end;

/


刪除流配置

conn strmadmin/strmadmin

exec dbms_streams_adm.remove_streams_configuration;


刪除流使用者

conn / as sysdba

drop user strmadmin cascade;


四、流複製的狀態查詢


檢視建立的流佇列和佇列表

select owner, name, queue_table, queue_type from dba_queues where owner = 'STRMADMIN';


OWNER      NAME                           QUEUE_TABLE                    QUEUE_TYPE

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

STRMADMIN  AQ$_STREAMS_QUEUE_TABLE_E      STREAMS_QUEUE_TABLE            EXCEPTION_QUEUE

STRMADMIN  STREAMS_QUEUE                  STREAMS_QUEUE_TABLE            NORMAL_QUEUE


檢視流佇列表資訊

select owner, queue_table, object_type from dba_queue_tables where owner = 'STRMADMIN';


OWNER      QUEUE_TABLE                    OBJECT_TYPE

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

STRMADMIN  STREAMS_QUEUE_TABLE            SYS.ANYDATA


檢視傳播程式資訊

col destination_dblink for a30

select propagation_name, source_queue_name, destination_queue_name, destination_dblink, status from dba_propagation;


PROPAGATION_NAME               SOURCE_QUEUE_NAME              DESTINATION_QUEUE_NAME         DESTINATION_DBLINK             STATUS

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

MAIN_TO_NODE2                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_2                       ENABLED

MAIN_TO_NODE1                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_1                       ENABLED


檢視捕獲程式資訊

select capture_name, queue_name, start_scn, status, capture_type from dba_capture;


CAPTURE_NAME                   QUEUE_NAME                      START_SCN STATUS     CAPTURE_TY

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

CAPTURE_STREAMS                STREAMS_QUEUE                     6156463 ENABLED    LOCAL


檢視應用程式資訊

select apply_name,queue_name,status from dba_apply;


APPLY_NAME                     QUEUE_NAME                     STATUS

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

APPLY_STREAMS                  STREAMS_QUEUE                  ENABLED


五、補充說明


1、可以基於Database級別或Table級別啟用追加日誌(Supplemental Log)

alter database add supplemental log data;


在建立根據Schema粒度進行復制的Oracle Stream環境中,如果確認Schema下所有Table都有合理的主鍵(Primary Key),則可不需要啟用追加日誌。


2、根據需要可修改傳播程式的休眠時間,如改為0,表示實時傳播

begin

    dbms_aqadm.alter_propagation_schedule(queue_name        => 'streams_queue',

                                          destination       => 'dl_mes_1',

                                          destination_queue => 'streams_queue',

                                          latency           => 0);

end;

/


3、如果等了很長時間資料還沒有複製過來,仔細檢查capture/propagation/apply各程式的狀態是否有異常。並可嘗試修改以下隱含引數並重啟

alter system set "_job_queue_interval"=1 scope=spfile;


4、如果本地節點長時間關閉或無法與主伺服器端保持網路連線,可能導致主伺服器端的傳播程式狀態變為disabled,此時即便恢復了連線,仍然不能保持正常的同步複製。這種情況可以嘗試先停止主伺服器端到本地節點的傳播程式,然後重新啟動傳播程式,一般情況下問題都可以得到解決。


查詢傳播程式狀態,發現到dl_mes_2的傳播是disabled

select propagation_name, source_queue_name, destination_queue_name, destination_dblink, status from dba_propagation;


PROPAGATION_NAME               SOURCE_QUEUE_NAME              DESTINATION_QUEUE_NAME         DESTINATION_DBLINK             STATUS

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

MAIN_TO_NODE1                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_1                       ENABLED

MAIN_TO_NODE2                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_2                       DISABLED


停止該傳播程式

begin

  dbms_propagation_adm.stop_propagation(propagation_name => 'main_to_node2',

                                        force            => true);

end;

/


此時該程式狀態變為aborted

select propagation_name, source_queue_name, destination_queue_name, destination_dblink, status from dba_propagation;


PROPAGATION_NAME               SOURCE_QUEUE_NAME              DESTINATION_QUEUE_NAME         DESTINATION_DBLINK             STATUS

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

MAIN_TO_NODE1                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_1                       ENABLED

MAIN_TO_NODE2                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_2                       ABORTED


重啟傳播程式

exec dbms_propagation_adm.start_propagation(propagation_name => 'main_to_node2');


檢視狀態已恢復正常

select propagation_name, source_queue_name, destination_queue_name, destination_dblink, status from dba_propagation;


PROPAGATION_NAME               SOURCE_QUEUE_NAME              DESTINATION_QUEUE_NAME         DESTINATION_DBLINK             STATUS

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

MAIN_TO_NODE1                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_1                       ENABLED

MAIN_TO_NODE2                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_2                       ENABLED


5、如果本地節點應用程式狀態變為abort,可嘗試以下操作


停止應用程式

exec dbms_apply_adm.stop_apply(apply_name => 'apply_streams');


檢視應用程式的報錯資訊

select * from dba_apply_error;


在確認錯誤已排除後,刪除錯誤資訊

exec dbms_apply_adm.delete_all_errors(apply_name=>'apply_streams');


重啟應用程式

exec dbms_apply_adm.start_apply('apply_streams');


再次檢查應用程式狀態是否已恢復為enabled

select apply_name,queue_name,status from dba_apply;


APPLY_NAME                     QUEUE_NAME                     STATUS

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

APPLY_STREAMS                  STREAMS_QUEUE                  ENABLED

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28974745/viewspace-2137631/,如需轉載,請註明出處,否則將追究法律責任。

相關文章