pureXML 作为数据库的一项新兴技术,已经获得越来越广泛的应用。在很多项目之中,需要利用 DB2 Replication Server 对 XML 数据进行复制,由于 XML 数据类型的特殊性,在项目实施过程中,经常会遇到复制的实施问题。本文通过实例详细介绍了 XML 数据类型的复制配置步骤,为 XML 的项目实施者提供一个参考。
DB2 提供两种复制方式,SQL 复制和 Q 复制。SQL 复制又称为 DB2 复制,它是通过 Capture 程序或者一些触发器捕获源表的改变,并将这些改变写入到 CD 表( Change Data Table )之中;然后由 Apply 程序从 CD 表之中读取改变,并用采用标准的 SQL 语句将这些改变应用到目标表上。Q 复制是结合数据日志捕获以及 WebSphere MQ 消息队列传输的一种复制方式,Q 捕获程序( Capture )读取 DB2 相关表的恢复日志,并通过队列将其发出,Q 应用程序将其获取并应用到目标数据库上。在下文中,我们将展示如何使用这两种复制方式对含有 XML 数据类型的数据库进行复制,使用的是 DB2 V9.7 版本。
DB2 V9.7 的 SQL 复制虽然增加了一些新的功能,如对 DB2 压缩表的支持,但是仍然只支持关系型数据的复制,不支持对 pureXML 数据的复制。为了能复制 pureXML 数据,我们需要做一些额外的工作。
pureXML 的 SQL 复制主要包括了如下对象:
- Capture 控制服务器:用于注册并捕获数据源表
- Apply 控制服务器:用于管理预订集并把数据复制到目标表
- 联合数据库对象:用于在目标数据库上访问源数据库的数据源表
下面我们具体说明其配置步骤。
在试验的过程之中我们需要两台机器,分别命名为 SOURCE 和 TARGET,源数据库和目标数据库分别位于这两台机器上。确认在这两台机器上都安装了 DB2 V9.7 以及在 TARGET 上安装了联邦服务器( Federation Server )。在 SOURCE 机器上创建 DB2 的 SAMPLE 数据库作为源数据库(采用 DB2 的“第一步”进行创建),在 TARGET 机器上创建 TSAMPLE 数据库作为目标数据库。这里需要注意的是,在创建 SAMPLE 数据库时,要选择 XML 和 SQL 对象和数据,这样才能够创建包含 XML 数据类型的表。
在进行进一步操作之前,我们需要确认 SAMPLE 数据库的存档模式是归档日志记录( Archive Logging )。因为在复制中,我们需要读取源数据库的日志来进行操作,默认的循环日志记录( Circular Logging ) 模式并不能满足这种需求。
1. 打开 SOURCE 和 TARGET 上的 db2set DB2COMM=TCPIP
2. 打开 db2clp,使用下面的命令在 TARGET 上编目 SOURCE 的 SAMPLE 数据库,指定编目数据库别名为 SAMPLE。
db2 catalog tcpip node SOURCE remote 9.123.149.23 server 50000 db2 catalog database SAMPLE at node SOURCE |
其中,9.123.149.23 是 SOURCE 的 IP ,50000 是 SOURCE 上 DB2 的服务端口。
3. 在 TARGET 上打开 DB2 复制中心( Replication Center )。在复制中心中,点击复制中心 -> 管理密码和连接,来创建密码和连接管理。首先分别创建 SOURCE 和 TARGET 系统连接,如图 1 所示。
图 1. 创建系统连接
注意,在“系统名称”一栏之中需要填入 SOURCE 的 IP 地址或者域名。再分别创建 SAMPLE 和 TSAMPLE 数据库服务器信息,如图 2 所示。
图 2. 创建数据库信息
4. 展开 SQL 复制 -> 定义 ->Capture 控制表,右键点击捕获控制表,选择创建 Capture 控制表 -> 快速模式,为 SAMPLE 快速创建 Capture 控制表并添加到 Capture 控制服务器中,在“服务器信息”页面输入 SAMPLE 数据库,并选择“主管复制的源并捕获对这些源的更改”,如图 3 所示。
图 3. 快速创建 Capture 控制表
之后的步骤全部采用默认设置,并点击确定。过程完成后,会发现 SAMPLE 数据库已被加入到 Capture 控制服务器列表中。右键点击 Capture 控制服务器列表中的 SAMPLE,选择“启用数据库以进行复制”,使日志捕获器在源数据库 SAMPLE 上生效(对数据库进行备份)。
5. 利用同步骤 4 相似的过程在 TSAMPLE 中创建 Apply 控制表并添加到 Apply 控制服务器中,注意的是在“服务器信息”页面选择“将捕获的更改应用于目标表”。
6. 在 Capture 控制服务器列表中选择 SAMPLE,将要复制的表注册到 Capture 控制服务器中。展开 SAMPLE 节点,在“Capture 模式”-->“ASN”-->“注册的表”节点上右键单击,选择“注册表”在打开的选择对话框里检索出所需要的表,这里以 SAMPLE 中的 CUSTOMER 表为例。由于 SQL 复制不支持 XML 列,因此在注册表时要取消 XML 列的捕获,如图 4 所示。其他设置均用默认设置即可。
图 4. 注册表
如果不取消 XML 列的捕获,就会有如下错误出现:
ASN1571E The database table “DB2ADMIN.CDCUSTOMER” cannot be created: the database definition is not valid for data type “XML” and column “INFO”. The reason code is “0”. |
此步中需要注意的是,必须选择“捕获所有列的改变”,而不能选择“只捕获已经注册列的改变”。 因为在这里我们并没有注册 XML 列的数据 . 如果错误的选择了“只捕获已经注册列的更改”, 当源表之中只对 XML 列(INFO 或者 HISTORY 列)的数据进行了更改,而并为更改 CID 列,由于 XML 列并非注册的列,Capture 程序将不会捕获在该列上的更新,在 Apply 程序端也将无法感知到源表中的 XML 数据列已经进行了更新,从而导致 XML 列上的更新无法复制到目标表中。
7. 为注册表建立复制预订集。右键单击注册好的 CUSTOMER 表,选择“创建预订集”。在弹出的对话框中,在“集信息”一栏选择 TSAMPLE 作为 Apply 控制服务器和目标服务器,输入预订集名和限定符,选中“激活预定集”,这样在 capture 启动的时候,预定集将被自动的激活。其他项均用默认设置即可。如图 5 所示。
图 5. 集信息
在 “源到目标映射”一栏可以指定目标表的 schema,表名等信息,如图 6 所示。不过此时要在 TSAMPLE 库上创建的 TGCUSTOMER 表将只会有在 CUSTOMER 表上捕获的 CID 列。在后面的步骤中,我们将会在 TGCUSTOMER 上加上 XML 类型的 INFO 和 HISTORY 列。
图 6. 源到目标映射
在“时间表” 一栏可以指明复制的频率,在测试的时候,可以将间隔的时间尽量的调小,如 1 分钟,这样每一个 Apply 处理周期的时间的为 1 分钟,源表数据的跟新能够很快的复制到目标表,如图 7 所示。
图 7. 时间表
其他都用默认设置,点击“确定”后将会出现运行窗口,显示了要运行的 SQL 语句,此时,我们可以找到 TGCUSTOMER 的创建语句,然后手动加上 XML 类型的 INFO 和 HISTORY 列的定义,如图 8 所示,之后点击“确定”,运行成功即可。
图 8. 添加 XML 列
如果在过程之中,忘记了手动的修改生成 sql 脚本添加 INFO 和 HISTORY 列,可以通过在命令行中执行下面 alter table 语句在目标表中增加这两列:
db2 alter table db2admin.tgcustomer add column INFO xml db2 alter table db2admin.tgcustomer add column HISTORY xml |
8. 在 TSAMPLE 数据库上建立联合数据库对象,访问 SAMPLE 数据库的 CUSTOMER 表,整个过程我们都可以通过 DB2 控制中心完成。在 TARGET 服务器的 DB2 控制中心中,右键单击 TSAMPLE 数据库下的“联合数据库对象”,选择“创建联合数据对象”。在弹出的对话框中创建“包装器”、“服务器”、“用户映射”和“昵称”,具体如图 9 至图 12 所示。( 需要对各个步骤进行讲解,每一步进行什么样的动作 )。
图 9. 创建包装器
该步中选择创建数据源类型 DB2, 其余的采用默认设置。
图 10. 创建服务器
在服务器定义中指定联合服务器的名称为 SAMPLE, 类型 DB2/UDB, 版本 9.7,然后指定连接 SAMPLE 数据库的用户名和密码,在设置中指定 DBNAME 参数的值为 SAMPLE。
图 11. 创建用户映射
为本地用户 DB2ADMIN 映射到远程用户 DB2ADMIN, 同时需要输入远程用户的密码。
图 12. 创建昵称
添加远程表 DB2ADMIN.CUSTOMER 的昵称。
接下来,我们将基于创建的联合数据库对象,使用两种不同的方案来实现 XML 数据的复制。
由于 SQL 复制中,可以指定用户自定义的 SQL 语句或者存储过程,Apply 程序在每一个预定集的处理周期前或处理完之后将会执行这些用户定义的 SQL 语句或者存储过程。在本方案中,我们便利用了 SQL 复制的这一功能。
本方案是对数据源表中的 XML 字段,在每个复制周期完成后,增加一个对新更改记录 XML 字段的 update 操作,直接将数据源的 XML 数据更新到目标表中的 XML 数据。其中关键是区分在目标表中,哪些记录需要更新;如果不能区分,当把 XML 数据复制到目标表时会出现大量的重复更新。为解决此问题,我们在目标表上增加一个标志字段,该字段对应复制处理的计算字段,赋值为常量,比如 1。当 Apply 程序在插入了新行,或者修改某行数据的时候,标志字段的值都会被重置为常量 1。在每一个处理周期之后的执行的 SQL 语句之中,通过对标志位进行判断,如果标志位是 1,则表明该行数据是新插入的行或者进行了更新,需要在 SQL 语句之中更新该行中的 XML 数据。在更新 XML 数据的同时,更新该标志字段将其置为 0,这样在之后的 Apply 周期如果 Apply 程序没有更新该行数据,SQL 语句不需要更新该行中的 XML 数据,从而避免了重复更新。
1. 在 TGCUSTOMER 表中,添加 flag 列。
db2 alter table db2admin.tgcustomer add column FLAG integer |
2. 打开预定集,在源到目标映射的标签下,对 CUSTOMER 表进行更改。在成员属性窗口中,点击列映射标签,增加计算列 flag,并将其设置为常量 1。
图 13. 添加计算列
3. 在预定中增加对 XML 字段更新的 update 语句。
update db2admin.tgcustomer t set info=(select info from db2admin.customer s where s.cid=t.cid), history=(select history from db2admin.customer s where s.cid=t.cid), flag=0 where flag=1 |
并在 SQLSTATE 栏中添加 02000, 以允许返回空行。当 Apply 程序执行该 SQL 语句的时候如果返回任何其他非零的 SQLSTATE 值,Apply 程序将认为 SQL 语句执行发生了错误。
在此需要注意的是,在何时提交 SQL 语句一览中应选择“处理预定集后在目标服务器上”。这样,update 语句就被加入到每个 Apply 周期完成后系统自动调用的 SQL 语句中,与复制流程集成。生成执行脚本并运行以后,预定集就进行了更改。
图 14. 更改 SQL 语句
3. 激活预订集,启动 Capture 和 Apply。可以看到,CUSTOMER 表中的数据被复制到 TGCUSTOMER 表上,包括 XML 数据。
由于 SQL 复制之中,当 Apply 程序将数据应用到目标表的时候是采用的一般的 Insert/Update/Delete SQL 语句进行操作的。如果目标表存在触发器,Apply 的程序在将数据应用到目标表的时候,是会激活目标表上的相应的触发器的。因此我们的第二个方案就是使用触发器来更新目标表的 XML 数据,使之与数据源表的 XML 数据保持同步。具体步骤是在 TSAMPLE 数据库上对 TGCUSTOMER 表建立触发器,以便复制 XML 数据。我们要分别建立对应 insert 和 update 的触发器,delete 操作无需建立触发器。本文触发器例子定义:
CREATE TRIGGER DB2ADMIN.TRI_INS_TGCUSTOMER NO CASCADE BEFORE INSERT ON DB2ADMIN.TGCUSTOMER REFERENCING NEW AS new FOR EACH ROW MODE DB2SQL BEGIN ATOMIC set (new.info,new.history)=(select info,history from customer where cid=new.cid); END# CREATE TRIGGER DB2ADMIN.TRI_UPD_TGCUSTOMER NO CASCADE BEFORE UPDATE ON DB2ADMIN.TGCUSTOMER REFERENCING NEW AS new FOR EACH ROW MODE DB2SQL BEGIN ATOMIC set (new.info,new.history)=(select info,history from customer where cid=new.cid); END# |
上面的两种方案都实现了对 XML 数据的复制,但是在不同的应用场景中这两种方案却有个各自的优缺点。
如果预定集的处理周期较长,在一个处理周期内,源表中的同一条数据可能进行了多次的修改。这种情况,方案一要优于方案二。当源表上有多次更新时,Apply 程序也会在目标表上相应进行多次的更新,方案二中每次 Apply 程序更新目标表都会激活触发器从而从源表中读取 XML 数据,这样一个处理周期内 XML 数据将会被读取和更新多次。
如果源表数据更新较为缓慢,同时目标表中数据量很大,方案二更加适合这种情况。方案一中,即使源表中数据没有更新,在每一个预定集的处理周期之后仍然会执行 SQL 语句,由于目标表数据量庞大,执行 SQL 语句会造成一定的资源浪费。这种场景中,如果采用方案一,通过在 flag 列上建立索引,能够有效的降低每次执行 SQL 语句的资源消耗。
由于两种方案都不是 SQL 复制自身所提供的复制 XML 数据的方法,它们天生就有一定缺陷。当源表只对非 XML 列数据进行了修改,两种方案都会对 XML 列的数据重新的读取并写入到目标表之中。如果源表列数很多,而只有极少的列是 XML 数据列,XML 列的数据较大,并且非 XML 列的数据比 XML 列的数据更新更加平凡,这个问题将会变得更加突出。针对这种情况,通过在源表之中增加 XML 数据更新的标识列,并创建一个 XML 列上的更新触发器,只有当更新 XML 列的时候才激活该触发器并设置标志位,可以有效的减少对 XML 列的重复更新。读者如有兴趣可以自行实现,此处不再赘诉。
Q 复制本身提供对 pureXML 数据复制的支持。在 Q 复制中复制 pureXML 数据和一般关系型的数据相同,并不需要额外的步骤。Q 复制包括单向复制( Unidirectional replication ),双向复制( Bidirectional replication ) 以及点对点复制( Peer-to-peer replication )。使用 Q 复制,重点需要创建以下两个对象:
- 复制队列图:指定用来发送和接收数据和控制消息的 Websphere MQ 队列。
- Q 预定:指定将要被复制到目标表上面去的行和列,具体配置步骤,可以参考“DB2 远程 Q 复制实践”,此处不再赘述。
本文介绍了针对 XML 数据类型的复制解决方案,重点介绍了实现 XML 的 SQL 复制的两种方法,以供参考。
学习
- 通过 developerWorks Information Management 专区获得关于 DB2、Informix、InfoSphere 以及 BI、CM 等软件产品的技术资料和最佳实践。
- 访问 DB2 9 技术资源中心了解 DB2 产品家族的更多产品信息和相关技术。
- 访问 Infosphere 产品专题,这里汇聚了关于 Infosphere Federation Server 数据复制相关的技术特性和相关学习资源。
- 随时关注 developerWorks 技术活动和 网络广播。
获得产品和技术
- 使用可直接从 developerWorks 下载的 IBM 产品评估试用软件构建您的下一个开发项目。
- 现在可以免费使用 DB2。下载 DB2 Express-C,这是为社区提供的 DB2 Express Edition 的免费版本,它提供了与 DB2 Express Edition 相同的核心数据特性,为构建和部署应用程序奠定了坚实的基础。
讨论