1 引言
Oracle Stream功能是為提高數據庫的高可用性而設計的,在Oracle 9i及之前的版本這個功能被稱為Advance Replication。Oracle Stream利用高級隊列技術,通過解析歸檔日志,將歸檔日志解析成DDL及DML語句,從而實現數據庫之間的同步。這種技術可以將整個數據庫、數據庫中的對象復制到另一數據庫中,通過使用Stream的技術,對歸檔日志的挖掘,可以在對主系統沒有任何壓力的情況下,實現對數據庫對象級甚至整個數據庫的同步。
解析歸檔日志這種技術現在應用的比較廣泛,Quest公司的shareplex軟件及DSG公司的realsync都是這樣的產品,一些公司利用這樣的產品做應用級的容災。但shareplex或是realsync都是十分昂貴的,因此你可以嘗試用Stream這個Oracle提供的不用額外花錢的功能。Oracle Stream對生產庫的影響是非常小的,從庫可以是與主庫不同的操作系統平台,你可以利用Oracle Stream復制幾個從庫,從庫可用於查詢、報表、容災等不同的功能。本文不談技術細節,只是以手把手的方式一步一步的帶你把Stream的環境搭建起來,細節內容可以查聯機文檔。
2 概述
主數據庫:
操作系統:Solaris 9
IP地址:192.168.10.35
數據庫:Oracle 10.2.0.2
ORACLE_SID:prod
Global_name:prod
從數據庫:
操作系統:AIX 5.2
IP地址:192.168.10.43
數據庫:Oracle 10.2.0.3
ORACLE_SID:h10g
Global_name:h10g
3 環境准備
3.1 設定初始化參數
使用pfile的修改init.ora文件,使用spfile的通過alter system命令修改spile文件。主、從數據庫分別執行如下的語句:
| 以下是引用片段: Sqlplus ‘/ as sysdba’ alter system set aq_tm_processes=2 scope=both; alter system set global_names=true scope=both; alter system set job_queue_processes=10 scope=both; alter system set parallel_max_servers=20 scope=both; alter system set undo_retention=3600 scope=both; alter system set nls_date_format='YYYY-MM-DD HH24:MI:SS' scope=spfile; alter system set streams_pool_size=25M scope=spfile; alter system set utl_file_dir='*' scope=spfile; alter system set open_links=4 scope=spfile; |
執行完畢后重啟數據庫。
3.2 將數據庫置為歸檔模式
設置log_archive_dest_1到相應的位置;設定log_archive_start為TRUE,即啟用自動歸檔功能;設定log_archive_format指定歸檔日志的命令格式。
舉例:
| 以下是引用片段: sqlplus ‘/ as sysdba’ alter system set log_archive_dest_1=’location=/yang/arch’ scope=spfile; alter system set log_archive_start=TRUE scope=spfile; alter system set log_archive_format=’ arch%t_%s_%r.arc’ scope=spfile; shutdown immediate; startup mount; alter database archivelog; alter database open; |
數據庫置為歸檔模式后,可以按如下方式檢驗一下:
| 以下是引用片段: SQL> archive log list Database log mode Archive Mode Automatic archival Enabled Archive destination /yang/arch Oldest online log sequence 534 Next log sequence to archive 536 Current log sequence 536 |
3.3 創建stream 管理用戶
3.3.1 創建主環境stream管理用戶
| 以下是引用片段: #以sysdba身份登錄 connect / as sysdba #創建主環境的Stream專用表空間 create tablespace tbs_stream datafile '/yang/oradata/prod/tbs_stream01.dbf' size 100m autoextend on maxsize unlimited segment space management auto; #將logminer的數據字典從system表空間轉移到新建的表空間,防止撐滿system表空間 execute dbms_logmnr_d.set_tablespace('tbs_stream'); #創建Stream管理用戶 create user strmadmin identified by strmadmin default tablespace tbs_stream temporary tablespace temp; #授權Stream管理用戶 grant connect,resource,dba,aq_administrator_role to strmadmin; begin dbms_streams_auth.grant_admin_privilege( grantee => 'strmadmin', grant_privileges => true); end; / |
3.3.2 創建從環境stream管理用戶
| 以下是引用片段: #以sysdba身份登錄 connect / as sysdba #創建Stream專用表空間,我的從庫用了ASM,這一步也可以參見3.3.1 create tablespace tbs_stream datafile '+VGDATA/h10g/datafile/tbs_stream01.dbf' size 100m autoextend on maxsize unlimited segment space management auto; #同樣,將logminer的數據字典從system表空間轉移到新建的表空間,防止撐滿system表空間 execute dbms_logmnr_d.set_tablespace('tbs_stream'); #創建Stream管理用戶 create user strmadmin identified by strmadmin default tablespace tbs_stream temporary tablespace temp; #授權Stream管理用戶 grant connect,resource,dba,aq_administrator_role to strmadmin; begin dbms_streams_auth.grant_admin_privilege( grantee => 'strmadmin', grant_privileges => true); end; / |
3.4 配置網絡連接
3.4.1配置主環境tnsnames.ora
主數據庫(tnsnames.ora)中添加從數據庫的配置。
| 以下是引用片段: H10G = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.43)(PORT = 1521)) ) (CONNECT_DATA = (SID = h10g) (SERVER = DEDICATED) ) ) |
3.4.2配置從環境tnsnames.ora
| 以下是引用片段: 從數據庫(tnsnames.ora)中添加主數據庫的配置。 PROD = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.35)(PORT = 1521)) ) (CONNECT_DATA = (SID = prod) (SERVER = DEDICATED) ) ) |
3.5 啟用追加日志
可以基於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; |
3.6 創建DBlink
根據Oracle 10gR2 Stream官方文檔,針對主數據庫建立的數據庫鏈的名字必須和從數據庫的global_name相同。
如果需要修改global_name,執行“alter database rename global_name to xxx”。
3.6.1創建主數據庫數據庫鏈
#以strmadmin身份,登錄主數據庫。
connect strmadmin/strmadmin
#建立數據庫鏈
create database link h10g connect to strmadmin identified by strmadmin using 'h10g';
3.6.2創建從數據庫數據庫鏈
#以strmadmin身份,登錄從數據庫。
connect strmadmin/strmadmin
#建立數據庫鏈
create database link prod connect to strmadmin identified by strmadmin using 'prod';
3.7 創建流隊列
3.7.1創建Master流隊列
| 以下是引用片段: #以strmadmin身份,登錄主數據庫。 connect strmadmin/strmadmin begin dbms_streams_adm.set_up_queue( queue_table => 'prod_queue_table', queue_name => 'prod_queue'); end; / |
3.7.2創建Backup流隊列
| 以下是引用片段: #以strmadmin身份,登錄從數據庫。 connect strmadmin/strmadmin begin dbms_streams_adm.set_up_queue( queue_table => 'h10g_queue_table', queue_name => 'h10g_queue'); end; / |
3.8 創建捕獲進程
| 以下是引用片段: #以strmadmin身份,登錄主數據庫。提醒一下,本文檔以hr用戶做示例。 connect strmadmin/strmadmin begin dbms_streams_adm.add_schema_rules( schema_name => 'hr', streams_type => 'capture', streams_name => 'capture_prod', queue_name => 'strmadmin.prod_queue', include_dml => true, include_ddl => true, include_tagged_lcr => false, source_database => null, inclusion_rule => true); end; / |
3.9 實例化復制數據庫
在主數據庫環境中,執行如下Shell語句。如果從庫的hr用戶不存在,建立一個hr的空用戶。
exp userid=hr/hr@prod file='/tmp/hr.dmp' object_consistent=y rows=y
imp userid=system/manager@h10g file='/tmp/hr.dmp' ignore=y commit=y log='/tmp/hr.log' streams_instantiation=y fromuser=hr touser=hr
3.10 創建傳播進程
| 以下是引用片段: #以strmadmin身份,登錄主數據庫。 connect strmadmin/strmadmin begin dbms_streams_adm.add_schema_propagation_rules( schema_name => 'hr', streams_name => 'prod_to_h10g', source_queue_name => 'strmadmin.prod_queue', destination_queue_name => 'strmadmin.h10g_queue@h10g', include_dml => true, include_ddl => true, include_tagged_lcr => false, source_database => 'prod', inclusion_rule => true); end; / #修改propagation休眠時間為0,表示實時傳播LCR。 begin dbms_aqadm.alter_propagation_schedule( queue_name => 'prod_queue', destination => 'h10g', latency => 0); end; / |
3.11 創建應用進程
| 以下是引用片段: #以strmadmin身份,登錄從數據庫。 connect strmadmin/strmadmin begin dbms_streams_adm.add_schema_rules( schema_name => 'hr', streams_type => 'apply', streams_name => 'apply_h10g', queue_name => 'strmadmin.h10g_queue', include_dml => true, include_ddl => true, include_tagged_lcr => false, source_database => 'prod', inclusion_rule => true); end; / |
3.12 啟動STREAM
| 以下是引用片段: #以strmadmin身份,登錄從數據庫。 connect strmadmin/strmadmin #啟動Apply進程 begin dbms_apply_adm.start_apply( apply_name => 'apply_h10g'); end; / #以strmadmin身份,登錄主數據庫。 connect strmadmin/strmadmin #啟動Capture進程 begin dbms_capture_adm.start_capture( capture_name => 'capture_prod'); end; / |
3.13 停止STREAM
| 以下是引用片段: #以strmadmin身份,登錄主數據庫。 connect strmadmin/strmadmin #停止Capture進程 begin dbms_capture_adm.stop_capture( capture_name => 'capture_prod'); end; / #以strmadmin身份,登錄從數據庫。 connect strmadmin/strmadmin #停止Apply進程 begin dbms_apply_adm.stop_apply( apply_name => 'apply_h10g'); end; / |
3.14 清除所有配置信息
要清楚Stream配置信息,需要先執行3.13,停止Stream進程。
| 以下是引用片段: #以strmadmin身份,登錄主數據庫。 connect strmadmin/strmadmin exec DBMS_STREAMS_ADM.remove_streams_configuration(); #以strmadmin身份,登錄從數據庫。 connect strmadmin/strmadmin exec DBMS_STREAMS_ADM.remove_streams_configuration(); |
4 測試場景
本文檔建立了針對hr用戶的Stream 復制環境,如果沒有特別聲明,以下測試場景均以hr用戶身份執行。
4.1 建一張表測試
主數據庫
SQL> CREATE TABLE TTT(id NUMBER PRIMARY KEY,
2 name VARCHAR2(50)
3 )
4 /
Table created.
從數據庫
SQL> desc TTT
Name Null? Type
---------- -------- -------------
ID NOT NULL NUMBER
NAME VARCHAR2(50)
4.2 表中插入一行數據
主數據庫
SQL> insert into ttt values (1,'sdfsdfsdfsdf');
1 row created.
SQL> commit;
Commit complete.
SQL>
從數據庫
SQL> select * from TTT;
ID NAME
---------- --------------------
1 sdfsdfsdfsdf
4.3 變更一下表的結構,添加一列
主數據庫
SQL> ALTER TABLE TTT ADD(age NUMBER(2));
Table altered
從數據庫
SQL> desc TTT
Name Null? Type
----------- -------- --------------
ID NOT NULL NUMBER
NAME VARCHAR2(50)
AGE NUMBER(2)
4.4 將表換一個表空間
主數據庫
SQL> SELECT table_name,tablespace_name FROM user_tables
2 WHERE table_name='TTT';
TABLE_NAME TABLESPACE_NAME
------------------------------ ------------------------------
TTT USERS
SQL> ALTER TABLE TTT MOVE TABLESPACE tbs_stream;
Table altered
SQL> SELECT table_name,tablespace_name FROM user_tables
WHERE table_name='TTT';
TABLE_NAME TABLESPACE_NAME
------------------------------ ------------------------------
TTT TBS_STREAM
從數據庫
SQL> SELECT table_name,tablespace_name FROM user_tables
WHERE table_name='TTT';
TABLE_NAME TABLESPACE_NAME
------------------------------ ------------------------------
TTT TBS_STREAM
4.5 表上Name列建一索引
主數據庫
SQL> CREATE INDEX ttt_name_idx ON TTT(name);
Index created
從數據庫
SQL> SELECT table_name, index_name FROM user_indexes WHERE table_name = 'TTT';
TABLE_NAME INDEX_NAME
------------------------------ ------------------------------
TTT TTT_NAME_IDX
TTT SYS_C005721
4.6 Rebuild索引測試
主數據庫
SQL> ALTER INDEX ttt_name_idx REBUILD;
Index altered
從數據庫
SQL> SELECT table_name, index_name FROM user_indexes WHERE table_name = 'TTT';
TABLE_NAME INDEX_NAME
------------------------------ ------------------------------
TTT TTT_NAME_IDX
TTT SYS_C005721
4.7 索引換一個表空間測試
主數據庫
SQL> ALTER INDEX ttt_name_idx REBUILD TABLESPACE tbs_stream;
Index altered
從數據庫
SQL> SELECT table_name,index_name,tablespace_name FROM user_indexes
WHERE table_name = 'TTT';
TABLE_NAME INDEX_NAME TABLESPACE_NAME
------------------------------ ------------------------------ ------------------------------
TTT TTT_NAME_IDX TBS_STREAM
TTT SYS_C005721 USERS
4.8 刪除索引測試
主數據庫
SQL> DROP INDEX ttt_name_idx;
Index dropped
從數據庫
SQL> SELECT table_name,index_name,tablespace_name FROM user_indexes
WHERE table_name = ‘TTT’;
TABLE_NAME INDEX_NAME TABLESPACE_NAME
------------------------------ ------------------------------ ------------------------------
TTT SYS_C005721 USERS
4.9 刪除表測試
主數據庫
SQL> DROP TABLE ttt;
Table dropped
從數據庫
SQL> DESC ttt;
Object ttt does not exist.
4.10 建一張帶有LOB類型字段的表測試
主數據庫
SQL> CREATE TABLE tttclob(id NUMBER PRIMARY KEY, memo CLOB);
Table created
從數據庫
SQL> DESC tttclob;
Name Null? Type
----------- -------- --------------
ID NOT NULL NUMBER
MEMO CLOB
4.11 表中插入一行數據
主數據庫
SQL> INSERT INTO tttclob VALUES(1,'clob_test');
1 row inserted
SQL> commit;
Commit complete
從數據庫
SQL> SELECT * FROM tttclob;
ID MEMO
---------- --------------------------------------------------------------------------------
1 clob_test
4.12 創建Type測試
主數據庫
SQL> CREATE or REPLACE TYPE ttttype;
2 /
Type created
從數據庫
SQL> SELECT * FROM user_types WHERE type_name='TTTTYPE';
TYPE_NAME TYPE_OID TYPECODE ATTRIBUTES METHODS PREDEFINED INCOMPLETE FINAL INSTANTIABLE SUPERTYPE_OWNER SUPERTYPE_NAME LOCAL_ATTRIBUTES LOCAL_METHODS TYPEID
------------------------------ -------------------------------- ------------------------------ ---------- ---------- ---------- ---------- ----- ------------ ------------------------------ ------------------------------ ---------------- ------------- --------------------------------
TTTTYPE 1B36AAF10DA8301DE040A8C0289A77B4 OBJECT 0 0 NO YES YES YES
4.13 刪除Type測試
主數據庫
SQL> DROP TYPE ttttype;
Type dropped
從數據庫
SQL> SELECT * FROM user_types WHERE type_name='TTTTYPE';
TYPE_NAME TYPE_OID TYPECODE ATTRIBUTES METHODS PREDEFINED INCOMPLETE FINAL INSTANTIABLE SUPERTYPE_OWNER SUPERTYPE_NAME LOCAL_ATTRIBUTES LOCAL_METHODS TYPEID
------------------------------ -------------------------------- -
5 問題診斷
5.1 如何知道捕捉(Capture)進程是否運行正常?
以strmadmin身份,登錄主數據庫,執行如下語句:
SQL> SELECT CAPTURE_NAME,
2 QUEUE_NAME,
3 RULE_SET_NAME,
4 NEGATIVE_RULE_SET_NAME,
5 STATUS
6 FROM DBA_CAPTURE;
結果顯示如下:
CAPTURE_NAME QUEUE_NAME
------------------------------ ------------------------------
RULE_SET_NAME NEGATIVE_RULE_SET_NAME STATUS
------------------------------ ------------------------------ --------
CAPTURE_PROD PROD_QUEUE
RULESET$_14 ENABLED
ENABLED
如果STATUS狀態是ENABLED,表示Capture進程運行正常;
如果STATUS狀態是DISABLED,表示Capture進程處於停止狀態,只需重新啟動即可;
如果STATUS狀態是ABORTED,表示Capture進程非正常停止,查詢相應的ERROR_NUMBER、ERROR_MESSAGE列可以得到詳細的信息;同時,Oracle會在跟蹤文件中記錄該信息。
5.2 如何知道Captured LCR是否有傳播GAP?
以strmadmin身份,登錄主數據庫,執行如下語句:
SQL> SELECT CAPTURE_NAME, QUEUE_NAME, STATUS, CAPTURED_SCN, APPLIED_SCN
2 FROM DBA_CAPTURE;
結果顯示如下:
CAPTURE_NAME QUEUE_NAME STATUS
------------------------------ ------------------------------ --------
CAPTURED_SCN APPLIED_SCN
------------ -----------
CAPTURE_PROD PROD_QUEUE ENABLED
17023672 17023672
如果APPLIED_SCN小於CAPTURED_SCN,則表示在主數據庫一端,要么LCR沒有被dequeue,要么Propagation進程尚未傳播到從數據庫一端。
5.3 如何知道Appy進程是否運行正常?
以strmadmin身份,登錄從數據庫,執行如下語句:
SQL> SELECT apply_name, apply_captured, status FROM dba_apply;
結果顯示如下:
APPLY_NAME APPLY_ STATUS
---------------------- ------ ----------------
APPLY_H10G YES ENABLED
如果STATUS狀態是ENABLED,表示Apply進程運行正常;
如果STATUS狀態是DISABLED,表示Apply進程處於停止狀態,只需重新啟動即可;
如果STATUS狀態是ABORTED,表示Apply進程非正常停止,查詢相應的ERROR_NUMBER、ERROR_MESSAGE列可以得到詳細的信息;同時,可以查詢DBA_APPLY_ERROR視圖,了解詳細的Apply錯誤信息。
6 結篇
通過如上的測試可以看出stream的功能還是十分強大的,通過配置Oracle Stream可以更大的提升數據庫的可用性和安全性,如此一個好用且不用花費高昂額外費用的功能還是很值得一用的。
轉:http://www.cnblogs.com/jerryxing/archive/2013/03/13/2957000.html
