Oracle Stream Replication技术
Stream 是Oracle 的消息隊列(也叫Oracle Advanced Queue)技術的一種擴展應用。 Oracle 的消息隊列是通過發布/訂閱的方式來解決事件管理。流復制(Stream replication)只是基于它的一個數據共享技術,也可以被用作一個可靈活定制的高可用性方案。 它可以實現兩個數據庫之間數據庫級,schema級,Table級的數據同步,并且這種同步可以是雙向的。 Oracle Stream也是通過數據冗余來提高可用性,這一點和Data Guard 類型。
Oracle 高級復制(Oracle advanced Replication) 和流復制(Stream Replication) 是從名稱和功能上都相似的兩種技術。 但前者是基于觸發器的,后者是基于日志挖掘(Logminer)技術。
?
?
?
1. Stream 的工作原理
?
Stream 是Oracle Advanced Queue技術的一種擴展應用, 這種技術最基本的原理就是收集事件,把時間保存在隊列中,然后把這些事件發布給不同的訂閱者。 從DBA的角度來說, 就是把捕獲Oracle數據庫產生的Redo日志,然后把這些日志通過網絡傳播到多個數據庫,其他數據庫通過應用這些日志,達到復制變化的作用。
在Stream 環境下, 復制的起點數據庫叫作Source Database, 復制的終點數據庫叫作Target Database。 在這兩個數據庫上都要創建一個隊列,其中的Source Database上的是發送隊列,而Target Database上的是接收隊列。
數據庫的所有操作都會被記錄在日志中。 配好Stream環境后, 在Source Database上會有一個捕獲進程(Capture Process), 該進程利用Logminer技術從日志中提取DDL,DML語句,這些語句用一種特殊的格式表達,叫作邏輯變更記錄(Logical Change Record, LCR). 一個LCR對應一個原子的行變更,因此源數據庫上的一個DML語句,可能對應若干個LCR記錄。 這些LCR會保存到Sourece Database的本地發送隊列中。然后傳播進程(Propagation Process)把這些記錄通過網絡發送到Target Database的接收隊列。 在Target Database上會有一個應用進程(Apply Process), 這個進程從本地的接收隊列中取出LCR記錄,然后在本地應用,實現數據同步
?
?
2. Data Guard 和Stream 區別
Date Guard有兩種類型:physical standby 和 logical standby。 這兩中standby 都有3個功能模塊: 日志傳送;日志接收,日志恢復。兩種standby在前兩個模塊中是一樣的,都是通過LGWR或者ARCn進程發送日志,通過RFS進程接受日志。 區別在第三個模塊:
Physical Standby 使用的是Media Recovery技術直接在數據塊級別進行恢復, 因此Physical Standby 能夠做到兩個數據庫的完全同步, 沒有數據類型限制。
Logical Standby實際是通過Logminer技術,把日志中的記錄還原成SQL語句,然后通過Apply Engine 執行這些語句實現數據同步, 因此Logical Standby不能保證數據的完全一致。 比如Logical Standby 不支持某些數據類型,這一點在選擇Logical Standby時必須要考慮. Logical Standby 不支持的數據類型可以從DBA_LOGSTDBY_UNSUPPORTED是不里查看.
SQL>SELECT * FROM DBA_LOGSTDBY_UNSUPPORTED;
?
?
Stream 使用的是Logical Standby 第三個模塊,也就是在Source Database一端,Capture 進程利用Logminer 技術把日志內容還原成LCR, 然后發送到Target Database, 而在Target database 一端, 也是通過Apply Engine 執行這些LCR。 因此Stream在使用上也有些限制條件。這些可以從視圖ALL/DBA_STREAMS_NEWLY_SUPPORTED, ALL/DBA_STREAMS_UNSUPPORTED 查看stream復制不支持的數據類型。
?
SQL>SELECT table_name, reason FROM ALL_STREAMS_NEWLY_SUPPORTED;
SQL>SELECT table_name, reason FROM DBA_STREAMS_NEWLY_SUPPORTED;
?
SQL>SELECT table_name, reason FROM DBA_STREAMS_UNSUPPORTED;
SQL>SELECT table_name, reason FROM ALL_STREAMS_UNSUPPORTED;
?
下面以圖表的形式列舉他們的區別:
| Streams | Data Guard |
| 主要目的是數據共享 | 主要目的是災難恢復和高可用性 |
| 可以多方向同步 | 只能是單向,從Primary--> Standby |
| 數據粒度可以是數據庫,Schema,Table三個級別 | 只有數據庫級別 |
| 支持異種平臺的同步(Heterogeneous Platforms) | 必須同種平臺 (Homogeneous Platforms) |
| 參與復制的每個數據庫可以讀寫 | 只有Primary可以讀寫,Standby 只讀 |
| 支持Oracle 和非Oracle 數據庫間的同步 | 只能是Oracle數據庫間 |
?
?
?
3. 前期規劃的幾點:
1). 確定復制集:如是數據庫級還是表級
2). 決定復制站點
3). 決定LCR是本地捕獲還是下游捕獲
本地捕獲: 在源數據庫進行,從聯機日志和歸檔日志獲得LCR
下游捕獲:在目標數據庫進行,從歸檔日志獲得LCR.
本地捕獲可以保護更多的數據,但是會占用源數據庫的資源。
4). 決定復制拓撲結構:這時要決定復制數據庫的用途,是只用于預防災難,還是平時保持空閑,或允許用戶使用。
?
?
?
?
?
?
4. Streams Replication 實例
?
4.1 準備工作:
DBA是源數據庫, DBA2是目標數據庫
?
4.1.1 源數據庫和目標數據庫必須是歸檔的
?
SQL> startup mount;
SQL> alter database archivelog;
SQL> alter database open;
SQL> archive log list
?
歸檔與非歸檔的切換請參考:
http://blog.csdn.net/tianlesoftware/archive/2009/10/18/4693470.aspx
或者
http://user.qzone.qq.com/251097186/blog/1236924069
?
4.1.2. 源數據庫和目的數據庫均需要設置的參數:
?
alter system set global_names=true scope = both;
默認為false, Database Link 使用的是數據庫的global_name。
alter system set aq_tm_processes=2 scope=both;
以下參數都是10G的默認值, 檢查下就可以了. 無需設置
如:Show parameter job_queue_processes
alter system set job_queue_processes = 10 scope=both;
alter system set sga_target = 300m scope=spfile;
alter system set open_links=4 scope=spfile;
alter system set statistics_level='TYPICAL' scope=both;
10g 默認為Typical, 性能統計模式
alter system set logmnr_max_persistent_sessions=1 scope=spfile;
10g 默認為1,持久的日志挖掘會話數。
alter system set "_job_queue_interval"=1 scope=spfile;
alter system set aq_tm_processes=1;
alter system set streams_pool_size=200m scope=both;
注意streams_pool_size一定要夠大,因為如果啟用了SGA_TARGET,ORACLE可能分配很少內存給stream導致大量信息被spill到磁盤導致查詢DBA_APPLY,DBA_CAPTURE,DBA_PROPGATION全部狀態ENABLED但就是沒有數據被同步。
同時設置_job_queue_interval也是為了提高隊列檢查時間,防止apply出問題。
注意:與復制有關的2個參數:
如果等了足夠長的時間發現數據沒有復制過來,仔細檢查了capture/propagation/apply各進程的狀態都是正常的, 并檢查參數.
alter system set "_job_queue_interval"=1 scope=spfile;
并且將aq_tm_processes參數改為1(我原來這是為10)
alter system set aq_tm_processes=1;
改完后重啟,發現數據就可以去了。這個隱含參數只是控制對job隊列的檢查頻率,默認5秒。
?
4.1.3 . 在源數據庫上啟用追加日志
可以基于Database級別或Table級別,啟用追加日志(Supplemental Log)。在建立根據Schema粒度進行復制的Oracle Stream環境中,如果確認Schema下所有Table都有合理的主鍵(Primary Key),則不再需要啟用追加日志。
#啟用Database 追加日志
alter database add supplemental log data;
?
#啟用Table追加日志
alter table add supplement log group log_group_name(table_column_name) always;
?
4.1.4 . 源數據庫和目的數據庫創建相同表空間和用戶并賦權
?
創建表空間:
CREATE TABLESPACE streams_tbs DATAFILE 'D:/ORACLE/ORADATA/DBA/streams_tbs.dbf' SIZE 100M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
CREATE TABLESPACE streams_tbs DATAFILE 'D:/ORACLE/ORADATA/DBA2/streams_tbs.dbf' SIZE 100M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
創建用戶:
CREATE USER strmadmin IDENTIFIED BY strmadmin DEFAULT TABLESPACE streams_tbs
QUOTA UNLIMITED ON streams_tbs;
賦權:
GRANT DBA to strmadmin; /* 10g要求dba角色以簡化配置 */
exec DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE('strmadmin'); /* 賦予流管理特權 */
?
4.1.5 配置listener.ora和tnsnames.Ora
DBA2 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.85.10.80)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DBA2.anqingren.org)
)
)
?
4.1.6 創建DBLink
?
先用strmadmin登陸,在創建dblink
?
4.1.6.1在源端建到目庫的db link
SQL> conn strmadmin/strmadmin;
已連接。
SQL> create database link DBA2 connect to strmadmin identified by strmadmin using 'dba2';
數據庫鏈接已創建。
?
測試:
SQL> select * from global_name@dba2;
GLOBAL_NAME
-------------------
DBA2.ANQINGREN.ORG
?
4.1.6.2 在目端建到源庫的db link
SQL> conn strmadmin/strmadmin;
已連接。
SQL> create database link dba connect to strmadmin identified by strmadmin using 'dba';
數據庫鏈接已創建。
?
?
4.2 用戶級的復制(不支持sys和system用戶)
?
4.2.1 最初的用戶復制
?
分別在源庫和目標數據庫上創建測試用戶
SQL>create user dave identified by dave;
SQL>grant dba to dave;
?
4.2.1 在源數據庫上創建Source 隊列
connect strmadmin/strmadmin@dba;
BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'SOURCE_QUEUE_TABLE', --隊列表
queue_name => 'SOURCE_QUEUE', --隊列
queue_user => 'strmadmin'); --隊列用戶
END;
/
或者:
SQL> EXEC DBMS_STREAMS_ADM.SET_UP_QUEUE();
PL/SQL procedure successfully completed.
?
該命令會創建一個隊列缺省名:streams_queue,隊列表缺省是:STREAMS_QUEUE_TABLE
隊列存儲的object類型是anaydata
?
移除隊列:
exec dbms_streams_adm.remove_queue(
queue_name => 'streams_queue',
cascade => true,
drop_unused_queue_table => true);.
?
?
可以用查詢dba_queues,dba_queue_tables來檢查:
SQL> select owner,queue_table,name from dba_queues where owner='STRMADMIN';
OWNER QUEUE_TABLE NAME
----------------- ------------------------- ------------------
STRMADMIN SOURCES_QUEUE_TABLE SOURCES_QUEUE
STRMADMIN SOURCES_QUEUE_TABLE AQ$_SOURCES_QUEUE_TABLE_E
?
SQL>select owner,queue_table,object_type from dba_queue_tables where owner='STRMADMIN';
OWNER QUEUE_TABLE OBJECT_TYPE
-------------- --------------------- ------------------
STRMADMIN SOURCES_QUEUE_TABLE SYS.ANYDATA
?
4.2.2 在目標數據庫DBA2上創建接收隊列
?
connect strmadmin/strmadmin@dba2;
BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'TARGET_QUEUE_TABLE', --隊列表
queue_name => 'TARGET_QUEUE', --隊列
queue_user => 'strmadmin'); --隊列用戶
END;
/
可以用查詢dba_queues,dba_queue_tables來檢查:
SQL> select owner,queue_table,name from dba_queues where owner='STRMADMIN';
OWNER QUEUE_TABLE NAME
------------------ --------------------- ----------------
STRMADMIN TARGET_QUEUE_TABLE TARGET_QUEUE
STRMADMIN TARGET_QUEUE_TABLE AQ$_TARGET_QUEUE_TABLE_E
?
4.2.3 在源數據庫上創建capture 進程
SQL>conn strmadmin/strmadmin@DBA;
SQL> BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name => 'dave', -- 用戶名,如dave, 非sys或者system
streams_type => 'capture',
streams_name => 'capture_stream',
queue_name => 'strmadmin.SOURCE_QUEUE',
include_dml => true,
include_ddl => true,
source_database => 'DBA',
include_tagged_lcr => false,
inclusion_rule => true);
END;
/
PL/SQL procedure successfully completed.
?
?
可以通過dba_capture查看:
SQL> select CAPTURE_NAME,QUEUE_NAME,START_SCN,STATUS,CAPTURE_TYPE from dba_capture;
CAPTURE_NAME QUEUE_NAME START_SCN STATUS CAPTURE_TY
------------------------- ---------------------------- ---------- -------------- ----------------
CAPTURE_STREAM1 SOURCES_QUEUE 1294052 DISABLED LOCAL
?
SQL> select * from ALL_CAPTURE_PREPARED_SCHEMAS;
SCHEMA_NAME TIMESTAMP SUPPLEME SUPPLEME SUPPLEME SUPPLEME
-------------------- -------------- -------- -------- -------- --------
SYSTEM 20-10月-09 IMPLICIT IMPLICIT IMPLICIT NO
?
4.2.4 在源數據庫上創建傳播進程
SQL>conn strmadmin/strmadmin@DBA;
SQL> BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
schema_name => 'dave',
streams_name => 'source_to_target',
source_queue_name => 'strmadmin.SOURCE_QUEUE',
destination_queue_name => 'strmadmin.TARGET_QUEUE@DBA2', --此隊列待創建
include_dml => true,
include_ddl => true,
source_database => 'DBA',
inclusion_rule => true,
queue_to_queue => true);
END;
/
PL/SQL procedure successfully completed.
?
重新啟動propagation process
--dbms_propagation_adm.start_propagation (propagation_name)
--其中propagation_name可以從表all_propagation中取得
select * from all_propagation;
SQL> exec dbms_propagation_adm.start_propagation('source_to_target');
exec dbms_propagation_adm.stop_propagation('source_to_target');
PL/SQL procedure successfully completed.
select * from all_propagation;
?
可以通過dba_propagations查看結果:
SQL> select PROPAGATION_NAME,SOURCE_QUEUE_NAME,DESTINATION_QUEUE_NAME,DESTINATION_DBLINK,STATUS from dba_propagation;
?
PROPAGATION_NAME SOURCE_QUEUE_NA DESTINATION_QUE DESTINATION_DBLINK STATUS
------------------ --------------- --------------- ------------------ --------
STREAM1_TO_STREAM2 SOURCES_QUEUE TARGET_QUEUE DBA2.ANQINGREN.ORG ENABLED
?
?
#修改propagation休眠時間為0,表示實時傳播LCR。
begin
dbms_aqadm.alter_propagation_schedule(
queue_name => 'SOURCE_QUEUE',
destination => 'DBA2',
latency => 0);
end;
/
?
?
4.2.5 在目標數據庫DBA2上創建Apply進程
?
SQL> BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name => 'SYSTEM',
streams_type => 'apply',
streams_name => 'target_apply_stream',
queue_name => 'strmadmin.TARGET_QUEUE',
include_dml => true,
include_ddl => true,
include_tagged_lcr => false,
source_database => 'DBA',
inclusion_rule => true);
END;
/
?
可以通過:
dba_apply
v$streams_apply_reader
v$streams_apply_coordinator
v$streams_apply_server
查看狀態
?
SQL> select apply_name,queue_name,status from dba_apply;
?
APPLY_NAME QUEUE_NAME STATUS
------------------------------ ------------------------------ --------
TARGET_APPLY_STREAM TARGET_QUEUE DISABLED
?
4.2.6 實例化復制數據庫
?
4.2.6.1 用exp/imp 完成實例化
?
帶數據完成源端exp和目端的import:
Exp USERID=SYSTEM/ADMIN@DBA OWNER=SYSTEM FILE=D:/STRM.dmp LOG=STRM.log OBJECT_CONSISTENT=Y STATISTICS = NONE
?
imp USERID=SYSTEM/ADMIN@DBA2 FULL=Y CONSTRAINTS=Y FILE=D:/STRM.dmp IGNORE=Y COMMIT=Y LOG=D:/import.log STREAMS_INSTANTIATION=Y
?
或僅作實例化(不帶數據):
exp USERID=SYSTEM/ADMIN@DBA OWNER=SYSTEM FILE=D:/STRM.dmp LOG=D:/export.log OBJECT_CONSISTENT=Y STATISTICS = NONE ROWS=NO
?
imp USERID=SYSTEM/ADMIN@DBA2 FULL=Y CONSTRAINTS=Y FILE=D:/STRM.dmp COMMIT=Y LOG=D:/import.log STREAMS_INSTANTIATION=Y IGNORE=Y
?
4.2.6.2 直接設置SCN的方式進行實例化:
---獲取源庫互置用戶的SCN
connect strmadmin/strmadmin@DBA
set serveroutput on
DECLARE
iscn NUMBER; -- Variable to hold instantiation SCN value
BEGIN
iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
DBMS_OUTPUT.PUT_LINE ('Instantiation SCN is: ' || iscn);
END;
/
---設置為目標庫互置用戶的SCN
connect strmadmin/strmadmin@DBA2
BEGIN
DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN(
source_schema_name => 'SYSTEM',
source_database_name => 'DBA',
instantiation_scn => &iscn);
END;
/
?
?
4.2.7. 在目標數據庫上啟動Apply進程
connect strmadmin/strmadmin@DBA2
SQL> BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(apply_name => 'target_apply_stream', parameter
=> 'disable_on_error', VALUE => 'n');
END;
/
?
SQL> BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name => 'target_apply_stream');
END;
/
#停止Apply進程
begin
dbms_apply_adm.stop_apply(
apply_name => 'target_apply_stream');
end;
/
?
查看狀態
SQL> select apply_name,queue_name,status from dba_apply;
?
APPLY_NAME QUEUE_NAME STATUS
------------------------------ ------------------------------ --------
TARGET_APPLY_STREAM TARGET_QUEUE ENABLED
?
?
4.2.8 在源數據庫上啟動capture
connect strmadmin/strmadmin@DBA
SQL> BEGIN
DBMS_CAPTURE_ADM.START_CAPTURE(
capture_name => 'capture_stream');
END;
/
#停止Capture進程
begin
dbms_capture_adm.stop_capture(
capture_name => 'capture_stream');
end;
/
?
查看狀態:
SQL> select capture_name,status from dba_capture;
CAPTURE_NAME STATUS
--------------- --------
CAPTURE_STREAM ENABLED
?
4.3 表級的復制
maintain_tts 表空間復制
maintain_schemas 用戶復制
maintain_tables 表復制的
與dbms_streams_adm的maintain_global、maintain_tts、maintain_schemas等過程相比,maintain_tables過程使用則更靈活,可以為某些特殊的表拿出來單獨配置,maintain_tables也象其它的過程一樣,提供了一藍子解決方案,如果要添加新的表到復制中,只需要再次執行maintain_tables過程即可。
4.3.1 在stream進行配置前,需要做些準備工作
A 源庫與目標庫初始化參數的設置
alter system set aq_tm_processes=1 scope=spfile;
alter system set job_queue_processes=2 scope=spfile;
alter system set global_names=true scope=spfile;
alter system set streams_pool_size=20m scope=spfile;
說明streams_pool_size在生產環境中最好>200m
B 源庫與目標庫tnsnames.ora配置
見4.1
C 源庫與目標庫復制管理員的創建
見4.1
D 在源庫與目標庫創建DBLINK
見4.1
E 源庫與目標庫必須處于歸檔模式
見4.1
F 源庫與目標庫必須創建directory
connect strmadmin/strmadmin@DBA;
create directory DIR_DBA as 'D:/Stream/DBA';
connect strmadmin/strmadmin@DBA2;
create directory DIR_DBA2 as 'D:/Stream/DBA2';
說明:在復制表空間時,創建directory需要指定該表空間所在的目錄
G 創建測試用的表空間及表
CREATE TABLESPACE DAVE DATAFILE 'D:/ORACLE/ORADATA/DBA/DAVE.dbf' SIZE 100M;
create user tianle identified by tianle default tablespace DAVE;
grant dba to tianle;
conn TIANLE/TIANLE
create table test(id int,name varchar2(20));
create table test2(id int,name varchar2(20));
insert into test values(1,'dave');
insert into test values(2,'bl');
不能使用默認的表空間.
4.3.2 在源庫執行MAINTAIN_TTS過程
SQL>connect strmadmin/strmadminpw@DBA;
declare
v_tables dbms_utility.uncl_array;
begin
v_tables(1) := 'tianle.test;
v_tables(2) := 'tianle.test2';
dbms_streams_adm.maintain_tables(
table_names => v_tables,
source_directory_object => null,
destination_directory_object => null,
source_database => 'DBA',
destination_database => 'DBA2',
perform_actions => true,
bi_directional => false,
include_ddl => true,
instantiation => dbms_streams_adm.instantiation_table_network);
end;
/
說明:在源庫執行maintain_tables時,目標庫幾乎什么都不用做,stream環境已經配置好啦,
如果想復制其它的表,只用再執行maintain_tables過程即可
4.3.3 如果在執行2的過程時失敗,需要清除腳本
--select script_id from dba_recoverable_script;
--exec dbms_streams_adm.RECOVER_OPERATION('&1','PURGE');
declare
v_script_id varchar2(32);
begin
select script_id into v_script_id from dba_recoverable_script;
dbms_streams_adm.RECOVER_OPERATION(v_script_id,'PURGE');
exception
when no_data_found then
DBMS_OUTPUT.PUT_LINe('no data found') ;
when others then
?
?
4.5 全庫級復制
以上主要為大家介紹了pre_instantiation_setup/post_instantiation_setup過程在配置全庫復制的方法,以下介紹dbms_streams_adm的maintain_global過程如何配置stream全庫復制方法,適用于10gR2及以后版本。
不支持sys/ system 用戶的變更。
1.在stream進行配置前,需要做些準備工作
?
a 源庫與目標庫初始化參數的設置
| alter system set aq_tm_processes=4 scope=spfile; |
說明streams_pool_size在生產環境中最好>200m
?
b 源庫與目標庫tnsnames.ora配置
見4.1
c 源庫與目標庫復制管理員的創建
見4.1
d 源庫與目標庫創建互連的DBLINK
見4.1
e 源庫與目標庫必須處于歸檔模式
見4.1
f 源庫與目標庫必須創建directory
create directory dir_DBA as 'D:/Stream/DBA';
create directory dir_DBA2 as 'D:/Stream/DBA2';
2.在源庫執行MAINTAIN_GLOBAL過程
begin
dbms_streams_adm.maintain_global(
source_directory_object =>'dir_DBA',
destination_directory_object =>'dir_DBA2',
source_database=>'DBA',
destination_database =>'DBA2',
perform_actions=>true,
include_ddl=>true,
instantiation=>DBMS_STREAMS_ADM.INSTANTIATION_FULL_NETWORK
);
end;
?
說明:在執行maintain_global時,源庫與目標庫必須創建directory,然后在源庫執行, 目標庫幾乎什么都不用做,stream環境已經配置完畢
轉載于:https://www.cnblogs.com/weixun/archive/2013/06/15/3137995.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Oracle Stream Replication技术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 同步博客到CSDN
- 下一篇: 百万数据下几种SQL性能测试