服务器 频道

在DB2 UDB中复制空间数据(中篇)

  【IT168 服务器学院】 清单 5. Capture 进程设置测试
 
INSERT
INTO   streets(id, name, track)
VALUES (1, ''my first street'',
   db2gse.ST_LineString (''linestring(10 10, 20 20)'', 1))@
SELECT id, VARCHAR(name, 20), wkb FROM cdstreets_repl_view@
ID          2                    WKB
----------- -------------------- ---
          1 my first street      -
  1 record(s) selected.

UPDATE streets
SET    name = ''different street''
WHERE  id = 1@
SELECT id, VARCHAR(name, 20), track_update FROM cdstreets@
ID          2                    TRACK_UPDATE
----------- -------------------- ------------
          1 my first street      -
          1 different street     -
  2 record(s) selected.

UPDATE streets
SET    (id, track) = ( 2, db2gse.ST_LineString(
          ''linestring (5 10, 5 20)'', 1) )
WHERE  id = 1@
SELECT id, VARCHAR(name, 20), track_update FROM cdstreets@
ID          2                    TRACK_UPDATE
----------- -------------------- ------------
          1 my first street      -
          1 different street     -
          2 different street     U
  3 record(s) selected.

  将视图注册为复制源

  启动 capture 进程之前的最后一步操作是将视图 STREETS_REPL_VIEW 注册为复制源。然后,可将该视图用于订阅组中。这张视图中包含着以已知二进制格式编码的空间数据。

  不幸的是,该视图并不能用 DB2 Replication Center 进行注册。复制工具会根据这张视图基于的所有表的 CD 表创建变化数据视图(CD 视图)。所有对该 CD 视图的引用必须找到对应的目标 CD 表。在我们的例子中,这就意味着如下的事实。CD 表中包含 ID、NAME 以及 TRACK_UPDATE 等字段。它并不包含 TRACK 字段,因为前面解释过,这个字段并不能注册。视图 STREET_REPL_VIEW 从表 STREETS 中引用 ID、NAME 和 TRACK 字段。相应的 CD 视图就必须引用 CD 表中相同的字段。 图7描述了这些依赖关系。

  图 7. 视图、表、CD 视图及 CD 表之间的依赖关系

 

  复制工具分析 STREETS_REPL_VIEW 的视图定义,发现字段 TRACK 是 ST_AsBinary() 函数的输入。但是,CD 表中没有相应的字段 TRACK,因此,CD 视图无法创建。您将看到如 图8所示的错误消息。

  图 8. 将 STREETS_REPL_SOURCE 注册为复制源的出错消息

 

  除了我已经说过的 CD 表中不存在 TRACK 字段的问题之外,我们还需要处理另外一个问题。最终得到的 CD 视图不应该包含 BLOB 字段(这个字段是 ST_AsBinary(TRACK) 这个函数调用的结果),而是应该包含更新指示器字段 TRACK_UPDATE。更新指示器已经存在于 CD 表中,所以这个依赖关系可以很轻易地满足。

  为了按照要求创建 CD 视图,我们现在要使用一个哑视图,它的基础表是 STREETS。 创建这张视图时应该包括 TRACK_UPDATE 字段,而不包括 TRACK 字段。而这个字段与 STREETS_REPL_VIEW 中经过转换以后的 TRACK 字段名字相同,即 WKB。 清单6是相应的 CREATE VIEW 语句。

清单 6. 创建包含更新指示器的哑视图

CREATE VIEW spatial_replication_dummy(id, name, wkb) AS
   SELECT t.id, t.name, t.track_update
   FROM   stolze.streets AS t@

  如 图9所示,注册这张视图的方法很简单。在注册过程中,我们也要给这张 CD 视图取一个更加恰当的名字。

  图 9. 注册哑视图

 

  用这种方法生成 SQL 语句非常简单,不会产生任何错误或者警告消息。您也可以就这样执行这些 SQL 语句。但是这个哑视图并不是我们实际想要复制的视图。因此,必须在复制目录表中修正该视图的名称。目录表 IBMSNAP_REGISTER 中的 SOURCE_OWNER 和 SOURCE_TABLE 包含了完全限定的表名。我们需要对这部分数据进行调整,令其指向视图 STREETS_REPL_VIEW。 清单7显示了当哑视图注册为复制源之后 IBMSNAP_REGISTER 表中的内容。

清单 7. IBMSNAP_REGISTER 目录表中的内容

SELECT source_owner, source_table FROM asn.ibmsnap_register@
SOURCE_OWNER    SOURCE_TABLE
--------------- -----------------------------
STOLZE          SPATIAL_REPLICATION_DUMMY
STOLZE          STREETS

  对这一项进行修改也是很简单的。您使用一条 UPDATE 语句就能实现必要的修正工作。当您修改完成之后,您可以将这张哑视图删除,因为已经不再需要它了。 清单8阐明了这两个步骤。

清单 8. 修正复制目录信息并清除哑视图
 
UPDATE asn.ibmsnap_register
SET    ( source_owner, source_table ) =
          ( ''STOLZE'', ''STREETS_REPL_VIEW'' )
WHERE  source_table = ''SPATIAL_REPLICATION_DUMMY''@
DROP VIEW spatial_replication_dummy@

  最后一步,您可以在 DB2 Replication Center 中双击正确的视图注册项。选中“Registered Views”,您就可以看到 STREETS_REPL_VIEW,如 图10所示。

  图 10. 验证已经注册的视图

 

  成功注册视图之后,您现在可以定义那些将视图作为复制源的订阅成员了,数据可以通过视图复制到不同数据库的目标表中。对目标表的设置将在下面几节中详细解释。

  准备目标数据库

  当我们将复制源映射到目标上时,目标通常是一张基表。但是在有些情况下可以用视图代替,空间数据复制正是这样的情况。如果使用的是目标视图,那么目标表和基于这张目标表的目标视图必须预先定义好,这样才能用 Replication Center 定义映射关系。过去,目标视图通常用于合并、联合或外联接的情况。现在,由于 DB2 UDB v8.1 中提供了 INSTEAD OF 触发器,使目标视图具备了全新的应用潜能。这种触发器可以在对视图发出 INSERT、UPDATE 或 DELETE 操作时引发不同的处理逻辑。因此,目标视图与这样的 INSTEAD OF 触发器相结合通常情况下能够在 Apply 进程处理过程中扩展数据传输的可能性。

  我们已经有了一张源视图,它执行从空间数据到外部数据格式的转换,也将这张视图注册为复制源,现在,我们可以在订阅成员中使用这张视图。空间数据转换成的 BLOB 并不受 DB2 Spatial Extender 的直接支持。而且 BLOB 并不是 ST_Geometry 值,因此不能在 Extender 所定义的各种不同的空间函数中作为输入参数。首先,我们必须执行逆向转换操作,将 BLOB 转换成几何图形类型。本节将一步步地解释如何设置目标数据库。

  概述

  由于空间数据的存在,我们必须对目标表做一些额外的处理。再次强调,复制工具不认识空间数据类型(或其他任何结构化类型),也不知道我们用已知二进制形式传输空间数据。我们必须实现一种机制,将二进制数据及时(即在 Apply 进程向目标表插入数据的时候)转换成相应的几何图形。

  有了 DB2 UD v8.1 及其后续版本中的 INSTEAD OF 触发器,我们可以实现一种非常简单的解决方案。我们先自己创建目标表,在其上定义视图,并为这张视图提供三个 INSTEAD OF 触发器,用于执行将外部数据格式转换成几何图形,并插入目标表中的工作。 图11更详细地解释了这个过程。请您注意,这个额外的过程使我们不能使用由复制工具生成的目标表。因此我们必须自己创建这些表。

  图 11. 在目标数据库上的处理过程

 

  创建基本表及视图

  第一步是创建基本表,并在基本表上创建视图与 INSTEAD OF 触发器。基本表和视图的定义很简单,可以从源数据库直接拷贝过来。但是我们不需要在目标表中增加更新指示器字段。 清单9重复了这些步骤。如果目标表在另一个数据库或另一个模式下的话,我们可以选择相同的表名与视图名。不过在本例中我用了一个前缀“TG_”,这样能更清楚地表明我引用的是哪一张表。

清单 9. 创建目标表,并在其上创建视图

CREATE TABLE tg_streets (
   id     INTEGER  NOT NULL  PRIMARY KEY,
   name   VARCHAR(200)  NOT NULL,
   track  db2gse.ST_LineString
)@
CREATE VIEW tg_streets_repl_view(id, name, wkb) AS
   SELECT t.id, t.name, db2gse.ST_AsBinary(t.track)
   FROM   stolze.tg_streets AS t@

  准备好表与视图之后,您可以创建三个 INSTEAD OF 触发器。一个触发器负责在把新的数据从数据源复制到目标表上时发生的 INSTERT 操作。第二个触发器处理 UPDATE,当数据同时存在于源表与目标表,而在源表上对其进行修改时,这个触发器就派上用场了。当在源表的记录上执行了 DELETE 操作时,第三个触发器负责从目标表中删除相应的数据。 清单10显示了在视图 TG_STREETS_REPL_VIEW 上定义的这三个视图。

清单 10. 在目标表的视图上定义 INSTEAD OF 触发器
 
CREATE TRIGGER tg_streets_repl_i INSTEAD OF
   INSERT ON tg_streets_repl_view
   REFERENCING NEW AS n
   FOR EACH ROW
   MODE DB2SQL
   INSERT
   INTO   tg_streets(id, name, track)
   VALUES ( n.id, n.name, db2gse.ST_LineString(n.wkb))@
CREATE TRIGGER tg_streets_repl_u INSTEAD OF
   UPDATE ON tg_streets_repl_view
   REFERENCING NEW AS n OLD AS o
   FOR EACH ROW
   MODE DB2SQL
   UPDATE tg_streets
   SET    ( id, name, track ) = ( n.id, n.name,
             db2gse.ST_LineString(n.wkb, 1) )
   WHERE  id = o.id@
CREATE TRIGGER tg_streets_repl_d INSTEAD OF
   DELETE ON tg_streets_repl_view
   REFERENCING OLD AS o
   FOR EACH ROW
   MODE DB2SQL
   DELETE
   FROM   tg_streets
   WHERE  id = o.id@

  现在,所有的设置都已经完成,您可以定义订阅集合(subscription set )及其成员了。

  创建订阅集合

  真正开始复制空间数据的第一个步骤是创建一个订阅集合(如果您还没有定义的话)。订阅集合通常是对若干张源表和目标表的映射进行分组。所谓映射是指定义从哪张源表将数据复制到哪张目标表。一个订阅集合中的所有映射会一起进行数据复制。您也可以定义若干个订阅集合,其中的每两个集合之间都是独立的。

  在此,我们创建一个空白的订阅集合。后续步骤中我们向这个集合里加入订阅成员。 图12显示了我们是如何定义一个名为 SPATIAL 的订阅集合的。capture server 名为 SPATIAL,这是源表所在的数据库,apply control server 名为 REPL,这是目标表所在的数据库。

  图 12. 创建一个新的订阅集合

 

  

  当然,您在创建订阅集合的时候就可以向其中加入部分或全部的成员。这可以通过“Create Subscription Set”对话框中的“Source-to-Target Mapping”面板来实现。我们现在不马上定义成员,而是用一个单独的步骤实现。用这种方法更容易实现反复增加新成员。

  有关创建订阅集合的更多细节,请参考 DB2 Replication User''s Guide and Reference 手册。

  增加空间数据的订阅成员

  设置好源表和目标表之后,我们现在就可以定义订阅成员了。这是空间数据复制过程中需要完成的最后一步管理任务。订阅成员的定义是小事一桩,我们用 DB2 Replication Center 来解释其中的每个操作步骤。

  首先,打开订阅集合名的上下文菜单,选中其中的“Add Member...”选项,以打开“Add Member to Subscription Set”窗口。在“Memeber Information”面板上,加入已经注册的源视图 STREETS_REPL_VIEW。DB2 Replication Center 会为新的目标表产生一个名称。您必须修改这个名称,使之指向您已经根据实际的目标表创建好的视图,如 图 13所示。

  图 13. 向订阅集合中增加成员

 

  您还需要修正更多的细节信息,因此请选择 Details...按钮,在打开的窗口中接着进行处理。我们当然想将 WKB 字段的内容复制过来了。所以我们要把这个字段加入到已选择字段清单中,如 图 14 所示。 图 14中的第二幅图片还显示出已经选择的字段 WKB 是如何映射到同样名为 WKB 的目标字段上的。您可以从左边的蓝色按钮上拉出一个箭头,放在右边的红色按钮上,这样就在两项之间建立起关系来。

  图 14. 将 WKB 字段加入到已选字段列表中

 

  下一步中会指明 ID 字段上存在索引,这更大程度上是出于提示信息的目的。我们知道这样的索引是作为底层基本表 TG_STREETS 的主键的一部分出现的。要完成成员属性的设置就必须进行这一步。 图15显示了其中的细节信息。

  图 15. 为目标表定义索引

 

  我们不想额外再定义记录过滤器,因此设置过程到此结束,点击“Member Properties”窗口和“Add Members to Subscription Sets”中的 OK按钮。所生成的语句分别在源数据库和目标数据库上执行,这样,成员的定义就完成了。

  启动 Capture 和 Apply 控制服务之后,所有的空间数据现在都可以正确复制了。 清单11中用一些小例子进行了验证。请注意,用常规文本表示的 SQL 语句集必须在源数据库中的源表 STREETS 上执行。以 粗体表示的查询语句从目标数据库的目标表 TG_STREETS 中获取数据。同时,在源数据库上的操作和数据向目标表传播之间存在延时。延时的长短取决于您在订阅集合中定义的时间表。语句在目标数据库上执行之后数据才复制成功,您必须等到这个时候才能看到如下所示的结果。

0
相关文章