java oracle 流复制_Oracle流复制技术
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 setopen_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-1、oraxe11g-2等
mes_1 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST =
oraxe11g-1)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = mes)
)
)
創建數據庫鏈接
對應各個本地節點的網絡服務名來創建,如dl_mes_1對應mes_1,dl_mes_2對應mes_2
create public database
link dl_mes_1 connect to system identified by mesHz2 using 'mes_1';
測試通過數據庫鏈接dl_mes_1、dl_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_name和destination_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;
創建RMES、BOSCH、ABS用戶并授權
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
導入主服務器端的RMES、BOSCH、ABS模式元數據
$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模式的更新,是否能夠自動同步到本地節點,包括DML和DDL操作。如未能同步,則檢查主服務器端和本地節點的警告日志信息,排查出錯原因。
表數據更新
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 procedurecmes.my_test(res
out varchar2) as
begin
res := 'OK';
end;
/
更新存儲過程
create
or replace procedurecmes.my_test(res
out varchar2) as
begin
res := 'NOK';
end;
/
刪除存儲過程
drop
procedurecmes.my_test;
6、建立流復制心跳
為監視流復制的工作狀態,在主服務器上創建心跳表
create
table cmes.streams_hb(hb_name
varchar2(20), hb_timevarchar2(20)) tablespace cmes;
插入數據
insert
into cmes.streams_hbvalues('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_hbset 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_0schemas=scott
include=table:"in('EMP')"table_exists_action=replace
三、流復制配置的刪除
停止應用進程
conn
strmadmin/strmadmin
execdbms_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
重啟傳播進程
execdbms_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,可嘗試以下操作
停止應用進程
execdbms_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
總結
以上是生活随笔為你收集整理的java oracle 流复制_Oracle流复制技术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云计算之多租户理解
- 下一篇: 2016-2045年新兴科技趋势报告