Oracle 高階複製配置步驟詳細說明

imlihj2007發表於2008-07-31

首先,資料庫要具備高階複製功能(用system身份登入資料庫,檢視v$option檢視,如果其中Advanced replicationTRUE,則支援高階複製功能;否則不支援)

.資料庫基本情況

資料庫A 版本oracle 10.2.0.3 資料庫名sid:shenzhen

資料庫B 版本oracle 10.2.0.3 資料庫名sid:beijing

主體定義站點:A shenzhen主體站點:B shenzhen:主體定義站點指配置複製工作的站點

本例涉及的使用者. 複製管理員:repadmin 應用使用者:cqm本例複製的物件:reptest 資料表 本例的先決條件:你需要設定好相應的引數,job_queue_processes需要大於0,global_name=true,並且建立相應的db link.

alter system set global_names=true scope=both;

.在兩個資料庫上分別建立應用使用者CQM

CREATE USER CQM IDENTIFIED BY CQM DEFAULT TABLESPACE users TEMPORARY TABLESPACE TEMP;

GRANT DBA TO CQM;

.在兩個資料庫上分別建立複製管事員使用者REPADMIN

--建立repadmin使用者管理複製環境

CREATE USER REPADMIN IDENTIFIED BY REPADMIN;

ALTER USER REPADMIN DEFAULT TABLESPACE USERS;

ALTER USER REPADMIN TEMPORARY TABLESPACE TEMP;

GRANT connect, resource TO REPADMIN;

--授予repadmin使用者許可權可以管理當前站點中任何主體組

EXECUTE dbms_repcat_admin.grant_admin_any_schema('REPADMIN');

--授予repadmin使用者許可權可以為任何表建立snapshot logs

GRANT comment any table TO REPADMIN;

GRANT lock any table TO REPADMIN;

--指定repadmin使用者為propagator,並授予執行任何procedure的許可權

EXECUTE dbms_defer_sys.register_propagator('REPADMIN');

GRANT execute any procedure TO REPADMIN;

.更改兩個資料庫的全域性名稱

alter database rename global_name to beijing.TEST.COM.CN;

alter database rename global_name to shenzhen.TEST.COM.CN;

.在兩個資料庫上建立資料庫連結

create public database link beijing.TEST.COM.CN connect to REPADMIN identified by REPADMIN using 'beijing';

create public database link shenzhen.TEST.COM.CN connect to REPADMIN identified by REPADMIN using 'shenzhen';

.在兩個資料庫的應用使用者CQM下建立表

在資料庫shenzhen上使用者CQM下:注意,要進行復制的表必須有主鍵

CREATE TABLE TEST(ID NUMBER(10),TIMESTAMP DATE DEFAULT sysdate);
ALTER TABLE TEST ADD(CONSTRAINT TEST_PK PRIMARY KEY(ID));

在資料庫beijing上使用者CQM下:

CREATE TABLE TEST(ID NUMBER(10),TIMESTAMP DATE DEFAULT sysdate);
ALTER TABLE TEST ADD(CONSTRAINT TEST_PK PRIMARY KEY(ID));

.在主體定義站點開始操作(資料庫A:shenzhen)

REPADMIN登入資料庫shenzhen

建立複製組:

execute dbms_repcat.create_master_repgroup('rep_hh'); [多餘的]
execute dbms_repcat.create_master_repgroup('repg');

在複製組裡加入複製物件:

execute dbms_repcat.create_master_repobject(sname=>'cqm',oname=>'test',type=>'table',use_existing_object=>true,gname=>'repg',copy_rows=>false);

對複製物件產生複製支援:

execute dbms_repcat.generate_replication_support('cqm','test','table');

execute dbms_repcat.drop_master_repobject ('scott','dept','table');[取消同步]

新增主體複製節點:

execute dbms_repcat.add_master_database(gname=>'repg',master=>'beijing.test.com.cn',use_existing_objects=>true,copy_rows=>false, propagation_mode => 'asynchronous');

  **********************************************   引數說明:   gname 主複製組名   master 加入主複製節點的另一個資料庫   use_existing_object true表示用主複製節點已經存在的資料庫物件   copy_rows false表示第一次開始複製時不用和主複製節點保持一致   propagation_mode 同步地執行 synchronous(上邊配置非同步複製)  ***********************************************

在主體定義站點啟動複製:

execute dbms_repcat.resume_master_activity('repg',true);

execute dbms_repcat.resume_master_activity('repg',false);

execute dbms_repcat.suspend_master_activity('repg')[停止複製]

.至此配置完成

附:

使用非同步複製要執行以下的過程!

exec dbms_defer_sys.schedule_push (destination => 'beijing.test.com.cn',interval => 'sysdate + 1/1440',next_date => sysdate);

exec dbms_defer_sys.schedule_purge (next_date => sysdate,interval => 'sysdate + 1/1440',delay_seconds => 0,rollback_segment => '');

***********************************************

exec dbms_defer_sys.schedule_push (destination => 'shenzhen.test.com.cn',interval => 'sysdate + 1/1440',next_date => sysdate);

exec dbms_defer_sys.schedule_purge (next_date => sysdate,interval => 'sysdate + 1/1440',delay_seconds => 0,rollback_segment => '');

這種配置方式對網路的影響比較小!管理也比較簡單


1)
模擬小資料量測試:OK
2)
模擬大資料量測試:OK
CREATE OR REPLACE procedure insert_into_test
as
i number;
m NUMBER;
n NUMBER;
BEGIN
n:=0;
FOR i IN 1..10000 LOOP
m:=i;
INSERT INTO test(id)VALUES (m);
n:=n+1;
IF n=1000 THEN
COMMIT;
n:=0;
END IF;
END LOOP;
COMMIT;
END;

新增複製物件的四個步驟!

execute dbms_repcat.suspend_master_activity('repg')

execute dbms_repcat.create_master_repobject(sname=>'cqm',oname=>'test1',type=>'table',use_existing_object=>true,gname=>'repg',copy_rows=>false);

execute dbms_repcat.generate_replication_support('cqm','test1','table');

execute dbms_repcat.resume_master_activity('repg',false)

execute dbms_repcat.resume_master_activity('repg',true)

附:

做完的時候開始插入資料有問題

SQL> insert into test(id) values(1);

insert into test(id) values(1)

*

ERROR at line 1:

ORA-04067: not executed, stored procedure "CQM.TEST$RP" does not exist

ORA-01085: preceding errors in deferred rpc to "CQM.TEST$RP.REP_INSERT"

ORA-02063: preceding 2 lines from BEIJING

後來就可以拉

1, 建立前資料要統一

2, 執行execute dbms_repcat.suspend_master_activity('repg')後源資料庫的表不可以再進行資料的插入!

3, Job 可以停到 並不影響資料的複製(表懷疑與搞笑)

4, 現在是同樣的作業系統同樣的資料庫版本

5, 以上是在同一作業系統下測試AIX5207

6, 高階複製如果目的站點有問題或者網路有問題!源站點的資料操作將會出錯!

7, 如果資料不同步的情況下,對源站點的資料操作會產生ORA-01403: no data found的問題!

8, 以上是資料的傳輸方式為同步的,如果修改成非同步的傳輸方式上邊的問題將不會出現的!

9, 不可以使用truncate table 清理資料

常用問題解答:

Q如何計算延遲事務將佔用多少的資源?
A
Deferred Transactions
Oracle forwards data replication information by propagating (that is, sending and executing) the RPCs that are generated by the internal triggers described previously. These RPCs are stored in the deferred transaction queue. In addition to containing the execution command for the internal procedure at the destination site, each RPC also contains the data to be replicated to the target site. Oracle uses distributed transaction protocols to protect global database integrity automatically and ensure data survivability.
Deferred Transaction Queue
This queue stores the transactions (for example, DML) that are bound for another destination in the master group. Oracle stores RPCs produced by the internal triggers in the deferred transaction queue of a site for later propagation. Oracle also records information about initiating transactions so that all RPCs from a transaction can be propagated and applied remotely as a transaction. Oracle's replication facility implements the deferred transaction queue using Oracle's advanced queuing mechanism.
上面是Oracle聯機文件中對於延遲事務和延遲事務佇列的描述。開始的時候一直以為延遲事務應該是存在Oracle的一個記憶體結構中,所以總是擔心如果複製環境中的網路長時間出現問題,那麼會不會導致延遲事務佇列佔用大量的記憶體而使資料庫的其它操作變慢,或者說超出了延遲事務可以使用的記憶體大小而產生錯誤。因為上面提到延遲事務佇列使用的是Oracle的高階佇列(Advanced Queue)演算法,所以又查詢了高階佇列的文件,發現多處提到Table這個詞,所以忽然明白所謂延遲事務的佇列應該是儲存在磁碟上的某些表中,這樣陡然就解決了心中很多疑問,首先事務多隻是佔用硬碟空間,其次要想計算事務佔用的資源可以透過表的block數來計算。於是透過SQL Trace,找到了延遲事務相關檢視的基表。
deftran
對應DEF$_AQCALL表,透過執行計劃也發現在統計大量延遲事務總數時候速度極為緩慢的原因,因為在作TABLE ACCESS FULL DEF$_AQCALL,同時還會作TABLE ACCESS FULL DEF$_AQERROR,還有UNION ALL的操作。
deferror
對應DEF$_ERROR表。defcall對應的也是DEF$_AQCALLDEF$_AQERROR表。現在我們檢查一下DEF$_AQCALL表的資訊。
SQL>; col owner for a10
SQL>; col object_name for a20
SQL>; select owner,object_name,object_id,data_object_id,object_type from dba_objects where object_name='DEF$_AQCALL';

OWNER OBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE
---------- -------------------- ---------- -------------- ------------------
SYS DEF$_AQCALL 3913 SYNONYM
SYSTEM DEF$_AQCALL 3861 3861 TABLE
SYSTEM DEF$_AQCALL 3869 QUEUE

Executed in 0.06 seconds
從上面的結果可以看到這個表是屬於SYSTEM的,在SYS下有一個同義詞。再檢查一下segment的情況,我們可以從dba_segments或者dba_extents檢視中檢視。
SQL>; col tablespace_name for a20
SQL>; select owner,tablespace_name,bytes,blocks from dba_segments where segment_name='DEF$_AQCALL';

OWNER TABLESPACE_NAME BYTES BLOCKS
---------- -------------------- ---------- ----------
SYSTEM SYSTEM 65536 8

Executed in 0.11 seconds
由此我們已經可以知道作為高階複製中延遲事務儲存所佔用的資源,同時由於這是普通的表,那麼當插入記錄的時候當然也是會快取在buffer cache中。這裡不作討論。也不再討論DEF$_AQERROR表,因為只有在延遲事務產生錯誤時才會插入,如果高階複製環境中沒有太多錯誤,這個表的資源佔用可以不考慮。
為了繼續驗證,現在測試環境中有REP_HOME複製組,其中的複製物件是SCOTT.EMP_2003表。斷開網路連線的情況下,我們插入10000條記錄。再次檢索DEF$_AQCALL表現在的情況。
SQL>; select owner,tablespace_name,bytes,blocks from dba_segments where segment_name='DEF$_AQCALL';

OWNER TABLESPACE_NAME BYTES BLOCKS
---------- -------------------- ---------- ----------
SYSTEM SYSTEM 2097152 256

Executed in 0.08 seconds
現在該表的大小已經擴大到2M,可以認為所有的複製資料和佇列資訊都儲存在這張表中。

SQL>; select count(*) from DEF$_AQCALL;

COUNT(*)
----------
10000

Executed in 0.04 seconds
再次證明確實是10000條資料。
如果此時我們用repadmin使用者檢索defcalldeftran檢視
SQL>; select count(*) from defcall;

COUNT(*)
----------
10000
已用時間: 00: 00: 02.04

SQL>; select count(*) from deftran;

COUNT(*)
----------
1
已用時間: 00: 00: 00.00
可以看到deftran檢視中只有一條記錄,因為上面的10000條資料的插入是一個事務中完成的,所以在複製環境中作為一個延遲事務處理。defcall中則是10000條記錄,詳細檢視內容,知道所有的cal事務號都相同,而callno不同,同時我們發現直接檢索DEF$_AQCALL只需要0.04秒,而檢索defcall檢視卻需要2秒,所以如果想要計算到底有多少資料需要處理的時候,我們可以直接從DEF$_AQCALL檢索,這樣可以縮短查詢時間。

Q:如果一張表沒有主鍵,又確實需要複製,怎麼辦?
A
:不建議在高階複製的環境中出現這樣的情況,應該確保每張表都有主鍵。如果確實存在這種情況,那麼需要用DBMS_REPCAT.SET_COLUMNS來生成代用主鍵。
execute DBMS_REPCAT.SET_COLUMNS(sname =>; test', oname =>; 'tabel', column_list =>; 'col1,col2,col3,col4');
其中column_list是用逗號隔開的欄位列表,不能有空格。注意:不要在執行set_columns之前生成對於沒有主鍵的物件的複製支援,也就是不要執行generate_replication_support,否則會導致all_repobject檢視中該物件狀態變為ERROR,而無法再次set_columns如果誤執行了複製支援而又沒有成功,那麼需要刪除掉這個複製物件再重新生成。也就是在對沒有主鍵的表生成複製的時候,必須遵循以下順序:
create_master_repobject ->; set_columns ->; generate_replication_support

Q:高階複製環境中出現長時間的網路問題會出現什麼情況?
A
:由於高階複製的傳播都是透過JOB來實現的,而大家知道Oracle對於JOB的執行有個限制,就是如果一個JOB執行失敗了16次,那麼這個JOB將會被標誌為BROKEN,以後這個JOB再也不會被自動執行,除非是手動設定BROKENFALSE或者手動成功地執行一次JOB這個特性給我們的實際應用中帶來了一些麻煩,假設我們的PUSH JOB定義的時間間隔是一分鐘,那麼如果主體站點之間的網路出現長時間的問題,比如說超過了16分鐘,也就是此時JOB已經失敗了16次,那麼PUSHJOB就被標誌為BROKEN了,這樣等到網路問題修復,會發現堆積的延遲事務也不會被PUSH到其它的主體站點上。如果不注意這個問題,往往就會出現嚴重的問題。解決方案是另外作一個JOB,這個JOB裡面每隔一定時間自動檢查那個PUSH JOB的狀態,如果是BROKEN的,那麼自動將其BROKEN狀態重新設定為FALSE,這樣下次又可以重新執行了。這個JOB中執行的儲存過程基本上如下:
DECLARE
CURSOR my_broken_jobs IS
SELECT job FROM user_jobs WHERE broken = 'Y';
BEGIN
FOR broken_job IN my_broken_jobs LOOP
BEGIN
dbms_job.broken(broken_job.job, FALSE);
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
END LOOP;
END;

Q:如果高階複製環境中的主體定義站點損壞,如何將主體定義站點切換到另外的主體站點上?
A
:分為兩種情況。備註:每次執行完repcat包以後都應該執行一次commit,因為某些rep的儲存過程是不會自動commit的,同時這也是一個troubleshooting,一般的rep指令碼都會較快的返回結果,如果一條命令之後長時間沒有結果返回,那麼很可能是上面的命令沒有commit,取消掉當前的命令,然後作一次commit,再重新執行,一般都能夠解決問題。一是隻有主體定義站點損壞。假設站點A是主體定義站點,已經損壞,在複製環境中還有站點B,想作為新的主體定義站點。
1
.以repadmin身份登入站點B,執行主體站點切換。
connect repadmin/repadmin
execute dbms_repcat.relocate_masterdef
(gname =>'repg',
old_masterdef =>'shenzhen.test.com.cn',
new_masterdef =>'beijing.test.com.cn',
notify_masters =>true,
include_old_masterdef =>false);

2
.將站點A作為主體站點刪除
execute dbms_repcat.remove_master_databases
(gname =>'repg',
master_list =>'shenzhen.test.com.cn');

3
.當站點A重新可用時,用repadmin使用者登入站點A,刪除其中的複製組資訊
connect repadmin/repadmin
execute dbms_repcat.drop_master_repgroup
(gname =>'repg',
drop_contents =>true,
all_sites => false);
如果要使站點A重新稱為複製環境中的一個主體站點,繼續執行下面的45兩步,否則切換主體定義站點就已經完成了。
4
登入站點B(新的主體定義站點)
connect repadmin/repadmin

execute dbms_repcat.suspend_master_activity
(gname =>'repg')

execute dbms_repcat.add_master_database
(gname => 'repg',
master =>'shenzhen.test.com.cn',
use_existing_objects =>true,
copy_rows =>false);

5
.重新開始複製
execute dbms_repcat.resume_master_activity
(gname =>'repg',true)
第二種情況是一些主體站點和主體定義站點同時損壞了。
1
.依次登入所有正常執行的主體站點,執行主體定義站點切換
execute dbms_repcat.relocate_masterdef
(sname =>; 'schemaname',
old_masterdef =>; 'oldmaster.world',
new_masterdef =>; 'newmaster.world',
notify_masters =>; false, /*
此處是false,而第一種情況中這個引數是true */
include_old_masterdef =>; false);
後面的操作步驟跟情況一相同,依次執行25就可以了。

Q:如何檢查一個錯誤的延遲事務到底作了什麼?
A
:有些時候因為種種原因,可能複製操作會出現錯誤。檢查DEFERROR檢視會發現有錯誤的延遲事務,我們首先可以透過DEFERRED_TRAN_IDCALLNODEFCALL檢視中查詢這個操作大體上是在幹什麼。
SQL>; select schemaname, packagename, procname from defcall;

SCHEMANAME PACKAGENAME PROCNAME
------------------------------ ------------------------------ ------------------------------
SCOTT EMP_2003$RP REP_DELETE
SCOTT EMP_2003$RP REP_DELETE

Executed in 0.06 seconds
其中SCHEMANAME表示哪個使用者執行的DMLPACKAGENAME中可以知道是哪個物件上的操作,PROCNAME則可以知道是插入,更新還是刪除。但是這樣的資訊往往不足夠我們判斷問題。我們想知道到底這個SQL幹了什麼,怎麼辦?我們可以利用DBMS_DEFER_QUERY.GET_CALL_ARGS來達到目的。執行以下的儲存過程,可以得到想要查詢的延遲事務的具體引數值。
CREATE OR REPLACE PROCEDURE GET_CALL(tran_id IN STRING,
callno IN NUMBER,
startarg IN NUMBER := 1,
argcnt IN NUMBER,
argsize IN NUMBER,
tran_db IN STRING := '') IS
v_types DBMS_DEFER_QUERY.TYPE_ARY;
v_vals DBMS_DEFER_QUERY.VAL_ARY;
indx NUMBER;
v_type_desc VARCHAR2(50);
BEGIN
DBMS_DEFER_QUERY.GET_CALL_ARGS(callno =>; callno,
startarg =>; startarg,
argcnt =>; argcnt,
argsize =>; argsize,
tran_db =>; tran_db,
tran_id =>; tran_id,
date_fmt =>; 'YYYY-MM-DD HH24:MI:SS',
types =>; v_types,
vals =>; v_vals);

FOR indx IN 1 .. argcnt LOOP
IF v_types(indx) = 1 THEN
v_type_desc := 'VARCHAR2';
END IF;
IF v_types(indx) = 2 THEN
v_type_desc := 'NUMBER';
END IF;
IF v_types(indx) = 12 THEN
v_type_desc := 'DATE';
END IF;
IF v_types(indx) = 23 THEN
v_type_desc := 'RAW';
END IF;
IF v_types(indx) = 96 THEN
v_type_desc := 'CHAR';
END IF;
IF v_types(indx) = 11 THEN
v_type_desc := 'ROWID';
END IF;
dbms_output.put_line('Arg ' || indx || ': Datatype ' ||
v_type_desc || '; Value: ' ||
v_vals(indx));
END LOOP;
END GET_CALL;
另外我們可以透過查詢DEF$_AQCALL 表的USER_DATA欄位也可以得到資料,這是一個BLOB欄位,提取BLOB欄位內容的方法這裡不再討論,如果有興趣的可以自己試一下

高階複製是oracle資料庫的高階功能,它的維護比普通資料庫複雜,下面是在已有高階複製資料庫維護過程中出現過一些問題和解決辦法。

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

相關文章