用ORACLE的高級復(fù)制實現(xiàn)內(nèi)外網(wǎng)數(shù)據(jù)同步
陳光 holen@263.net 2003.10
本文簡要介紹了ORACLE的高級復(fù)制功能,并通過一個實際項目,討論了在內(nèi)外網(wǎng)的兩級DB中如何采用高級復(fù)制達(dá)到內(nèi)外網(wǎng)的數(shù)據(jù)統(tǒng)一,最后給出配置腳本供大家參考。
1、基本概念
ORACLE
ORACLE是以高級結(jié)構(gòu)化查詢語言(SQL)為基礎(chǔ)的大型關(guān)系數(shù)據(jù)庫,通俗地講它是用方便邏輯管理的語言操縱大量有規(guī)律數(shù)據(jù)的集合。是客戶/服務(wù)器(CLIENT/SERVER)體系結(jié)構(gòu)的數(shù)據(jù)庫之一。
高級復(fù)制
什么是復(fù)制?簡單地說復(fù)制就是在由兩個或者多個數(shù)據(jù)庫系統(tǒng)構(gòu)成的一個分布式數(shù)據(jù)庫環(huán)境中拷貝數(shù)據(jù)的過程。
高級復(fù)制,是在組成分布式數(shù)據(jù)庫系統(tǒng)的多個數(shù)據(jù)庫中復(fù)制和維護(hù)數(shù)據(jù)庫對象的過程。 Oracle 高級復(fù)制允許應(yīng)用程序更新數(shù)據(jù)庫的任何副本,并將這些更改自動傳遞到其他數(shù)據(jù)庫,同時確保全局事務(wù)處理的一致性和數(shù)據(jù)完整性。
同步復(fù)制,復(fù)制數(shù)據(jù)在任何時間在任何復(fù)制節(jié)點均保持一致。如果復(fù)制環(huán)境中的任何一個節(jié)點的復(fù)制數(shù)據(jù)發(fā)生了更新操作,這種變化會立刻反映到其他所有的復(fù)制節(jié)點。這種技術(shù)適用于那些對于實時性要求較高的商業(yè)應(yīng)用中。
異步復(fù)制,所有復(fù)制節(jié)點的數(shù)據(jù)在一定時間內(nèi)是不同步的。如果復(fù)制環(huán)境中的其中的一個節(jié)點的復(fù)制數(shù)據(jù)發(fā)生了更新操作,這種改變將在不同的事務(wù)中被傳播和應(yīng)用到其他所有復(fù)制節(jié)點。這些不同的事務(wù)間可以間隔幾秒,幾分種,幾小時,也可以是幾天之后。復(fù)制節(jié)點之間的數(shù)據(jù)臨時是不同步的,但傳播最終將保證所有復(fù)制節(jié)點間的數(shù)據(jù)一致。
2、項目情況
需求描述
這是一個內(nèi)外網(wǎng)結(jié)構(gòu)的審批系統(tǒng)。
外網(wǎng)有一個WEB(+APPSERVER),一個DB(ORACLE9.2,雙網(wǎng)卡),負(fù)責(zé)接收申報和反饋審批結(jié)果。
內(nèi)網(wǎng)有一個WEB(+APPSERVER),一個DB(ORACLE9.2,雙網(wǎng)卡),負(fù)責(zé)接收申報和反饋審批結(jié)果,以及通過審批流程處理來自外網(wǎng)的審批申報。
由上可知,內(nèi)網(wǎng)功能包括外網(wǎng)功能,不過外網(wǎng)申報需要CA認(rèn)證,內(nèi)網(wǎng)則不需要。
根據(jù)國家保密有關(guān)規(guī)定,政務(wù)系統(tǒng)的內(nèi)外網(wǎng)必須物理隔絕,所以外網(wǎng)接收到的申報并不能馬上反應(yīng)到內(nèi)網(wǎng),同理,內(nèi)網(wǎng)的處理結(jié)果也不能迅速反饋到外網(wǎng)。
技術(shù)選擇`
我們選擇ORACLE異步手工復(fù)制,復(fù)制主要完如下功能:
1. 把外網(wǎng)新申報數(shù)據(jù)復(fù)制到內(nèi)網(wǎng);
2. 把內(nèi)網(wǎng)對申報的處理結(jié)果反饋到外網(wǎng)。
操作實現(xiàn)
因為正常工作時間,內(nèi)外網(wǎng)均不能停頓,而內(nèi)外網(wǎng)又不能物理連通。于是設(shè)定在每天晚上18:00至18:15(或其它時段)為維護(hù)時段,該時段內(nèi)外網(wǎng)均停止作業(yè),由系統(tǒng)管理員把與內(nèi)外網(wǎng)DB相連的所有網(wǎng)線均斷開,用一根直連網(wǎng)線把兩臺DB連接,通過ORACLE提供的操作界面,在外網(wǎng)端手工刷新記錄。
3、具體實現(xiàn)步驟
以下是腳本中用到的技術(shù)參數(shù),內(nèi)外網(wǎng)表結(jié)構(gòu)相同,且都有主鍵。
|
內(nèi)網(wǎng) |
外網(wǎng) |
IP |
192.168.0.50 |
192.168.0.100 |
SID |
ORANEI |
ORAWAI |
表 |
LAWTABLE REGISTER USERINFO …… 共68張表 |
LAWTABLE REGISTER 共2張表 |
登錄名/密碼 |
HOLEN/HOLEN |
HOLEN/HOLEN |
以下是我們到客戶處安裝所用的SQL腳本
第一步:配置內(nèi)網(wǎng),即MASTER端 |
--版本:2.0 --修訂者:陳光 holen@263.net --時間:2003-6-8 15:30 --內(nèi)網(wǎng)作為MASTER --創(chuàng)建內(nèi)網(wǎng)用戶HOLEN CONN SYSTEM/PASSWORD@ORANEI CREATE USER "HOLEN" PROFILE "DEFAULT" IDENTIFIED BY "HOLEN" ; GRANT "CONNECT" TO "HOLEN"; GRANT "DBA" TO "HOLEN"; GRANT "RESOURCE" TO "HOLEN"; --導(dǎo)入內(nèi)網(wǎng)數(shù)據(jù)庫備份,在dos下到入完成(表LAWTABLE,REGISTER及其他表) |
第二步:配置內(nèi)網(wǎng),即MASTER端(續(xù)) |
--需要復(fù)制(同步)的表為HOLEN用戶下的LAWTABLE,REGISTER --創(chuàng)建repadmin用戶管理復(fù)制環(huán)境 CREATE USER REPADMIN IDENTIFIED BY REPADMIN; ALTER USER REPADMIN DEFAULT TABLESPACE USERS; ALTER USER REPADMIN TEMPORARY TABLESPACE TEMP; GRANT connect, resource TO REPADMIN; --授予repadmin用戶權(quán)限可以管理當(dāng)前站點中任何主體組 EXECUTE dbms_repcat_admin.grant_admin_any_schema('REPADMIN'); --授予repadmin用戶權(quán)限可以為任何表創(chuàng)建snapshot logs GRANT comment any table TO REPADMIN; GRANT lock any table TO REPADMIN; --指定repadmin用戶為propagator,并授予執(zhí)行任何procedure的權(quán)限 EXECUTE dbms_defer_sys.register_propagator('REPADMIN'); GRANT execute any procedure TO REPADMIN; --分配proxy snapshot administration權(quán)限給repadmin,list_of_gnames為null,意味著可以管理所有對象組 BEGIN dbms_repcat_admin.register_user_repgroup( username => 'repadmin', privilege_type => 'proxy_snapadmin', list_of_gnames => NULL); END; / --分配'receiver'權(quán)限給repadmin BEGIN dbms_repcat_admin.register_user_repgroup( username => 'repadmin', privilege_type => 'receiver', list_of_gnames => NULL); END; / GRANT select any table TO repadmin; --在ORANEI上建立主體組,主體組名為HOLEN_MASTER,并往主體組中加入一個表 --建立復(fù)制主體組 BEGIN DBMS_REPCAT.CREATE_MASTER_REPGROUP( gname => '"HOLEN_MASTER"', qualifier => '', group_comment => ''); END; / CONNECT REPADMIN/REPADMIN; --向復(fù)制組中加入表對象LAWTABLE BEGIN DBMS_REPCAT.CREATE_MASTER_REPOBJECT( gname => '"HOLEN_MASTER"', type => 'TABLE', oname => '"LAWTABLE"', sname => '"HOLEN"', copy_rows => TRUE, use_existing_object => TRUE); END; / --建立相應(yīng)的快照日志 CREATE SNAPSHOT LOG ON "HOLEN"."LAWTABLE" TABLESPACE "SYSTEM" WITH PRIMARY KEY EXCLUDING NEW VALUES; --生成復(fù)制支持 BEGIN DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT( sname => '"HOLEN"', oname => '"LAWTABLE"', type => 'TABLE', min_communication => TRUE, generate_80_compatible => FALSE); END; / --向復(fù)制組中加入表對象REGISTER BEGIN DBMS_REPCAT.CREATE_MASTER_REPOBJECT( gname => '"HOLEN_MASTER"', type => 'TABLE', oname => '"REGISTER"', sname => '"HOLEN"', copy_rows => TRUE, use_existing_object => TRUE); END; / CREATE SNAPSHOT LOG ON "HOLEN"."REGISTER" TABLESPACE "SYSTEM" WITH PRIMARY KEY EXCLUDING NEW VALUES; BEGIN DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT( sname => '"HOLEN"', oname => '"REGISTER"', type => 'TABLE', min_communication => TRUE, generate_80_compatible => FALSE); END; / --MASTER端配置完畢 |
第三步:配置外網(wǎng),即SNAPSHOT端 |
--外網(wǎng)作為SNAPSHOT --創(chuàng)建外網(wǎng)用戶HOLEN CONN SYSTEM/PASSWORD@ORAWAI --創(chuàng)建普通用戶 CREATE USER "HOLEN" PROFILE "DEFAULT" IDENTIFIED BY "HOLEN"; GRANT "CONNECT" TO "HOLEN"; GRANT "DBA" TO "HOLEN"; GRANT "RESOURCE" TO "HOLEN"; --創(chuàng)建repadmin用戶管理快照端復(fù)制環(huán)境 CREATE USER REPADMIN IDENTIFIED BY REPADMIN; ALTER USER REPADMIN DEFAULT TABLESPACE USERS; ALTER USER REPADMIN TEMPORARY TABLESPACE TEMP; GRANT connect, resource TO REPADMIN; --授予repadmin用戶權(quán)限可以管理當(dāng)前站點中任何主體組 EXECUTE dbms_repcat_admin.grant_admin_any_schema('REPADMIN'); --授予repadmin用戶權(quán)限可以為任何表創(chuàng)建snapshot logs GRANT comment any table TO REPADMIN; GRANT lock any table TO REPADMIN; --指定repadmin用戶為propagator,并授予執(zhí)行任何procedure的權(quán)限 EXECUTE dbms_defer_sys.register_propagator('REPADMIN'); GRANT execute any procedure TO REPADMIN; --授予repadmin用戶可以創(chuàng)建快照 GRANT create any snapshot TO REPADMIN; GRANT alter any snapshot TO REPADMIN; --在外網(wǎng)建立與內(nèi)網(wǎng)的鏈接 --在外網(wǎng)端需要把ORANEI添加到樹 CREATE PUBLIC DATABASE LINK ORANEI CONNECT TO REPADMIN IDENTIFIED BY REPADMIN USING ' ORANEI '; --在外網(wǎng)建立刷新組 HOLEN_REFRESH BEGIN DBMS_REFRESH.MAKE( name => '"HOLEN"."HOLEN_REFRESH"', list => '', next_date => SYSDATE, interval => '/*1:Mins*/ sysdate + 1/(60*24)', implicit_destroy => FALSE, lax => FALSE, job => 0, rollback_seg => NULL, push_deferred_rpc => TRUE, refresh_after_errors => TRUE, purge_option => NULL, parallelism => NULL, heap_size => NULL); END; / --在外網(wǎng)建立快照組 BEGIN DBMS_REPCAT.CREATE_SNAPSHOT_REPGROUP( gname => '"HOLEN_MASTER"', master => 'ORANEI.US.ORACLE.COM', propagation_mode => 'ASYNCHRONOUS'); END; / --建立快照,快照要在表所屬的用戶下建立,本例要先用HOLEN用戶登陸 CONNECT HOLEN/HOLEN; --建立快照LAWTABLE CREATE SNAPSHOT "HOLEN"."LAWTABLE" REFRESH FAST FOR UPDATE AS SELECT * FROM "HOLEN"."LAWTABLE"@ ORANEI.US.ORACLE.COM C / --將快照加入刷新組 BEGIN DBMS_REFRESH.ADD( name => '"HOLEN"."HOLEN_REFRESH"', list => '"HOLEN"."LAWTABLE"', lax => TRUE); END; / --將快照加入快照組 BEGIN DBMS_REPCAT.CREATE_SNAPSHOT_REPOBJECT( gname => '"HOLEN_MASTER"', sname => '"HOLEN"', oname => '"LAWTABLE"', type => 'SNAPSHOT', min_communication => FALSE); END; / --建立快照REGISTER CREATE SNAPSHOT "HOLEN"."REGISTER" REFRESH FAST FOR UPDATE AS SELECT * FROM "HOLEN"."REGISTER"@ ORANEI.US.ORACLE.COM C / --將快照加入刷新組 BEGIN DBMS_REFRESH.ADD( name => '"HOLEN"."HOLEN_REFRESH"', list => '"HOLEN"."REGISTER"', lax => TRUE); END; / --將快照加入快照組 BEGIN DBMS_REPCAT.CREATE_SNAPSHOT_REPOBJECT( gname => '"HOLEN_MASTER"', sname => '"HOLEN"', oname => '"REGISTER"', type => 'SNAPSHOT', min_communication => FALSE); END; / --外網(wǎng)端(SNAPSHOT)配置完畢 |
第四步:配置內(nèi)網(wǎng) |
--當(dāng)外網(wǎng)配置完成后,在內(nèi)網(wǎng)執(zhí)行如下語句 BEGIN DBMS_REPCAT.RESUME_MASTER_ACTIVITY( gname => '"HOLEN_MASTER"'); END; / |
4、后記
ORACLE的高級復(fù)制功能非常強(qiáng)大,能實現(xiàn)多點間的數(shù)據(jù)同步、異步復(fù)制。
內(nèi)外網(wǎng)結(jié)構(gòu)的報送、審批、備案等兩(多)級系統(tǒng)日益流行,若內(nèi)外DB為同類型商業(yè)數(shù)據(jù)庫,一般數(shù)據(jù)庫本身都提供復(fù)制功能,若內(nèi)外網(wǎng)為不同類型的數(shù)據(jù)庫,如內(nèi)網(wǎng)為SQLSERVER,外網(wǎng)為ORACLE,則一般使用“同步機(jī)”中間件,在程序中調(diào)用即可。
感謝李鑫為我提供技術(shù)解答!
5、關(guān)于作者
陳光,J2EE項目經(jīng)理,熟悉EJB、XML,致力Aapche Jakarta、Aapche XML項目的應(yīng)用與推廣,可通過holen@263.net與作者聯(lián)系。