UML软件工程组织

用ORACLE的高级复制实现内外网数据同步
作者: 陈光

本文简要介绍了ORACLE的高级复制功能,并通过一个实际项目,讨论了在内外网的两级DB中如何采用高级复制达到内外网的数据统一,最后给出配置脚本供大家参考。

1、基本概念

ORACLE

ORACLE是以高级结构化查询语言(SQL)为基础的大型关系数据库,通俗地讲它是用方便逻辑管理的语言操纵大量有规律数据的集合。是客户/服务器(CLIENT/SERVER)体系结构的数据库之一。

高级复制

什么是复制?简单地说复制就是在由两个或者多个数据库系统构成的一个分布式数据库环境中拷贝数据的过程。

高级复制,是在组成分布式数据库系统的多个数据库中复制和维护数据库对象的过程。 Oracle 高级复制允许应用程序更新数据库的任何副本,并将这些更改自动传递到其他数据库,同时确保全局事务处理的一致性和数据完整性。

同步复制,复制数据在任何时间在任何复制节点均保持一致。如果复制环境中的任何一个节点的复制数据发生了更新操作,这种变化会立刻反映到其他所有的复制节点。这种技术适用于那些对于实时性要求较高的商业应用中。

异步复制,所有复制节点的数据在一定时间内是不同步的。如果复制环境中的其中的一个节点的复制数据发生了更新操作,这种改变将在不同的事务中被传播和应用到其他所有复制节点。这些不同的事务间可以间隔几秒,几分种,几小时,也可以是几天之后。复制节点之间的数据临时是不同步的,但传播最终将保证所有复制节点间的数据一致。

2、项目情况

需求描述

       这是一个内外网结构的审批系统。

外网有一个WEB(+APPSERVER),一个DB(ORACLE9.2,双网卡),负责接收申报和反馈审批结果。

内网有一个WEB(+APPSERVER),一个DB(ORACLE9.2,双网卡),负责接收申报和反馈审批结果,以及通过审批流程处理来自外网的审批申报。

由上可知,内网功能包括外网功能,不过外网申报需要CA认证,内网则不需要。

根据国家保密有关规定,政务系统的内外网必须物理隔绝,所以外网接收到的申报并不能马上反应到内网,同理,内网的处理结果也不能迅速反馈到外网。

技术选择

我们选择ORACLE异步手工复制,复制主要完如下功能:

1.  把外网新申报数据复制到内网;

2.  把内网对申报的处理结果反馈到外网。

操作实现

因为正常工作时间,内外网均不能停顿,而内外网又不能物理连通。于是设定在每天晚上18:00至18:15(或其它时段)为维护时段,该时段内外网均停止作业,由系统管理员把与内外网DB相连的所有网线均断开,用一根直连网线把两台DB连接,通过ORACLE提供的操作界面,在外网端手工刷新记录。

3、具体实现步骤

以下是脚本中用到的技术参数,内外网表结构相同,且都有主键。

 

  内网 外网
IP 192.168.0.50 192.168.0.100
SID ORANEI ORAWAI
LAWTABLE
REGISTER
USERINFO
……
共68张表
LAWTABLE
REGISTER
共2张表
登录名/密码 HOLEN/HOLEN HOLEN/HOLEN

以下是我们到客户处安装所用的SQL脚本

第一步:配置内网,即MASTER端

--版本:2.0
--修订者:陈光 holen@263.net
--时间:2003-6-8 15:30                   
--内网作为MASTER   
--创建内网用户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";

--导入内网数据库备份,在dos下到入完成(表LAWTABLE,REGISTER及其他表)

第二步:配置内网,即MASTER端(续)

--需要复制(同步)的表为HOLEN用户下的LAWTABLE,REGISTER

--创建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;

--分配proxy snapshot administration权限给repadmin,list_of_gnames为null,意味着可以管理所有对象组

BEGIN

  dbms_repcat_admin.register_user_repgroup(

  username =>       'repadmin',

  privilege_type => 'proxy_snapadmin',

  list_of_gnames =>  NULL);

END;

/

--分配'receiver'权限给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,并往主体组中加入一个表

--建立复制主体组

BEGIN

   DBMS_REPCAT.CREATE_MASTER_REPGROUP(

   gname => '"HOLEN_MASTER"',

   qualifier => '',

   group_comment => '');

END;

/

CONNECT REPADMIN/REPADMIN;

--向复制组中加入表对象LAWTABLE

BEGIN

   DBMS_REPCAT.CREATE_MASTER_REPOBJECT(

   gname => '"HOLEN_MASTER"',

   type => 'TABLE',

   oname => '"LAWTABLE"',

   sname => '"HOLEN"',

   copy_rows => TRUE,

   use_existing_object => TRUE);

END;

/

--建立相应的快照日志

CREATE SNAPSHOT LOG

     ON "HOLEN"."LAWTABLE"

TABLESPACE "SYSTEM"

WITH PRIMARY KEY

EXCLUDING NEW VALUES;

--生成复制支持

BEGIN  

   DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT(

   sname => '"HOLEN"',

   oname => '"LAWTABLE"',

   type => 'TABLE',

   min_communication => TRUE,

   generate_80_compatible => FALSE);

END;

/

--向复制组中加入表对象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端配置完毕

第三步:配置外网,即SNAPSHOT端

--外网作为SNAPSHOT   

--创建外网用户HOLEN

CONN SYSTEM/PASSWORD@ORAWAI

--创建普通用户

CREATE USER "HOLEN"  PROFILE "DEFAULT" IDENTIFIED BY "HOLEN";  

GRANT "CONNECT" TO "HOLEN";

GRANT "DBA" TO "HOLEN";

GRANT "RESOURCE" TO "HOLEN";

--创建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;

--授予repadmin用户可以创建快照

GRANT create any snapshot TO REPADMIN;

GRANT alter any snapshot TO REPADMIN;

--在外网建立与内网的链接

--在外网端需要把ORANEI添加到树

CREATE PUBLIC DATABASE LINK ORANEI CONNECT TO REPADMIN IDENTIFIED BY REPADMIN USING ' ORANEI ';

--在外网建立刷新组 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;

/

--在外网建立快照组

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;

/

--外网端(SNAPSHOT)配置完毕

第四步:配置内网

--当外网配置完成后,在内网执行如下语句

BEGIN   

   DBMS_REPCAT.RESUME_MASTER_ACTIVITY(

   gname => '"HOLEN_MASTER"');

END;

/

4、后记

ORACLE的高级复制功能非常强大,能实现多点间的数据同步、异步复制。

内外网结构的报送、审批、备案等两(多)级系统日益流行,若内外DB为同类型商业数据库,一般数据库本身都提供复制功能,若内外网为不同类型的数据库,如内网为SQLSERVER,外网为ORACLE,则一般使用“同步机”中间件,在程序中调用即可。

感谢李鑫为我提供技术解答!


关于作者

陈光,J2EE项目经理,熟悉EJB、XML,致力Aapche Jakarta、Aapche XML项目的应用与推广,可通过holen@263.net与作者联系。

来源:ZDNet China

 

版权所有:UML软件工程组织