处理逻辑
这一工具的处理逻辑遵从 捕获空间数据的变化和准备目标数据库两节的描述。只有当源表尚未注册为复制表时才能对其进行设置。如果注册已经完成,系统会简单地重用以前的定义。如果不是这种情况,那么工具会向源表中加入更新指示器字段、创建源视图,以及注册源表和源视图,从而创建 CD 表与 CD 视图。
在目标系统一方,工具也允许目标表已经存在。但是工具不会验证其字段和数据类型是否(与源表)匹配。如果目标表不存在,就创建一张。在这个阶段中我们也把源表的主关键字定义应用到目标表上。这个主关键字对于 INSTEAD OF 触发器的正常工作而言是必不可少的。带触发器的目标视图在订阅成员定义之前创建。
工具用于创建视图和触发器的模式名为 DB2SE_REPL。请您注意,视图的非限定性名称与表的非限定性名称相同。这意味着用这种方法设置的表都必须具备惟一的非限定性名称;也就是说,如果您的两个不同模式中都有名为 TAB 的表,那么 db2se_repl 工具将无法成功为这两张表设置复制。
复制专用的所有命令都是用 asnclp 工具执行的。因此,这个工具并没有在对空间数据的处理之上又实现什么特殊的逻辑。请注意,并不是 asnclp 的所有可能选项都被传递到 db2se_repl 的接口上。我们致力于实现一个简单的接口,它不具备丰富的特性。比如说,如果您想要调整订阅集合的时间安排,或改变其类型(默认条件下定义的是只读的订阅集合),那么您应该要么自己创建订阅集合,那么在 db2se_repl 创建好之后到 DB2 Replication Center 中对其进行适当的修改。
示例输出
捕获空间数据的变化和准备目标数据库这两节使用表 STREETS 进行复制。工具也能实现上面描述的相同步骤, 清单 12 向您展示了这个过程是如何完成的。在我们的例子中,我们用名为 src_DB 的数据库作为源数据库,目标数据库是 TGT_DB。表 STREETS 放置在源数据库的模式 S 和目标数据库的模式 T 中。输出信息为您简短地描述了设置的过程。
清单 12. 用 db2se_repl 设置 STREETS 的复制 |
当成功执行设置之后,您可以启动 capture 和 apply 服务器,对源表 S.STREETS 中的空间数据或其他数据所作的所有修改都会被捕获到,并应用到目标表 T.STREETS 或者您定义的其他任何目标数据库上。您现在可以运行清单 11 中列出的那些测试,验证一下空间数据复制的设置是否能正常工作。
说明
上面描述的复制空间数据的方法并没有提到 DB2 Spatial Extender 或 DB2 Replication 中所有各种不同的细节情况。现在让我们来看看其中的几个问题。
并非复制问题 —— 地理编码 (geocoding)
有一个非常重要的问题需要谈一下,您可能并不一定在所有的情况下都用上面描述的方法来复制空间数据。如果您的源表或目标表上具备地理编码器(geocoder)那么您可以从表中的其他字段,如地址字段等,再次生成空间数据。您可以对地址字段进行复制,这样就具备了对地址进行地理编码的全部必要信息,又可以生成相应的空间数据值。
根据地址数据生成空间数据的过程称为地理编码。地理编码器就是实现了地理编码算法的一个函数。 DB2 Spatial Extender User''s Guide and Reference 中提供了一种架构,可以支持很多种不同的地理编码器。您也可以编写您自己的用户定义函数(user-defined function,UDF),将地址数据作为输入参数,将其转换成空间数据。地址数据可以是任何形式的非空间数据;它并不一定非得是“555 Bailey Ave. San Jose, CA 95141”这种真实世界中的地址。
如果您把地理编码器和您的复制方案结合起来使用,以便不复制空间数据自身,那么您就会使用到如 图16 所示的一种设置。源表上有一个地理编码器,它根据同一张表中的地址数据生成空间数据 (1)。源表中包含着空间数据,访问源表的应用程序也可以使用这些空间数据。当把源表中的信息复制到目标表中时,您将复制包含地址数据的字段,但不复制空间数据字段 (2)。在目标数据库中,您再次使用地理编码器将地址数据转换成空间数据 (3)。地理编码必然在每一行数据上都发生两次:一次在源表上,另一次在目标表上。 图16总结了上面描述的这种设置。空间字段由蓝色标出,在源表上的地理编码、复制、在目标表上对地址数据的地理编码这三个不同的步骤已经被编上数字。
![]() |
在很多情况下,我们可能并不希望在目标表上对地址数据进行额外的地理编码操作。比如说,如果您使用了一个地理编码器,您就必须接受两次运行地理编码器带来的性能损失。另一个问题应该是,地理编码器可能不能对所有的地址进行编码。您可以为某些地理编码器不能处理的地址手工设置坐标。这种手工操作必须在复制数据上重复进行。此外,如果您使用[3] 中描述的 Web 服务,那么很可能对地理编码器本身的使用也是强制收费的。对同一地址在复制之后再次进行地理编码,这样会增加单个地址的处理费用。在这种情况下,本文中介绍的技术对您来说也许是一种可行的选择,当然它对管理和设置的要求也是较高的。
请注意,如果您采用附加字段和触发器将空间数据转换成 LOB,类似地理编码器的方法也还是可以用的。触发器将重新产生附加字段的值(让我们称其为 SPATIAL_LOB 字段)。在对源表中的数据进行复制时,您也复制了 SPATIAL_LOB 字段中的数据。在目标表上,您将使用相同的方法,把复制过来的数据存储在一个单独的字段中。您可以再次使用触发器从复制过来的 LOB 生成空间数据。因为重新构造数据的时候使用的是空间函数,您可以简单地认为这些函数就是“地理编码器”,我们又一次面临上面已经解释过的情况。这种方法的缺点显然是要占用额外的磁盘空间,以及需要在源表的用户事务上执行到 LOB 的转换。我们提出的技术仅仅要求使用最小的磁盘空间(需要增加一个 CHAR(1) 字段),转换的工作量完全是由 Apply 进程处理的。
空间字段的 INLINE LENGTH
INLINE LENGTH 这方面的问题本文一直都没有提及。当创建表的时候,您应该考虑空间字段的 INLINE LENGTH 参数的定义。INLINE LENGTH 定义了结构化类型最大占据多少字节,在这个范围内结构化类型还是像 VARCHAR FOR BIT DATA 那样与一条记录的其他数据存储在一起。如果结构化的数值过长,就要像 BLOB 那样存储在一个与表相关联的长表空间中。INLINE LENGTH 越大,能与表中其余数据一起存储的(空间)数据就越多。
像 VARCHAR FOR BIT DATA 那样存储结构化数据的好处显然在于,这样的值可以缓存在 DB2 的缓冲区池中,而 LOB 是直接从磁盘上读写的,I/O 量较大。
复制中的可选项
DB2 复制还提供了很多其他的选项,可以用来对复制机制进行控制。举例来说,您可以改变时间表,在复制过程中的某些特定点上运行额外的 SQL 语句,对订阅集合进行分组并指派不同的限定符,创建索引、过滤记录、指定表空间,等等。所有这些选项大都和本文描述的空间数据复制方法是正交关系。
复制 LOB
空间数据转换成 LOB、对 LOB 进行复制、然后又在目标表上转换回空间数据。这种借用 LOB 的方法意味着复制 LOB 时需要考虑的特殊问题在复制空间数据时同样需要考虑。比如说,Apply 进程会从源表中选择最新版本的空间数据。这个版本可能和 CD 表中获得的记录中的其他数据并不是同一版本,这种不一致的情况在下一次 Apply 周期中将会得到修正,但是您应该了解这种可能性。
结束语
本文向您展示了一种利用 DB2 UDB V8.1 和 DB2 Replication 复制空间数据的方法。我们遵从已有的技术,用一张基于源表的视图将空间数据转换成外部数据格式(在我们的例子中是二进制)。相应的 CD 表和 CD 视图都需要作些许调整才能适应我们的需要。对源表进行适当的设置之后,Apply 进程就能以 BLOB 的形式捕获到空间数据发生的所有变化,并将其应用到目标视图上。再加上三个 INSTEAD OF 触发器,这张视图就相当于给 Apply 进程定义了一个操作的接口。触发器定义了逆向转换过程,从而再次构造出与源表中一样的空间数据。这一过程得到的结果是空间数据的一种无缝复制。我们详细地描述了如何设置源表和视图,以及目标表及其视图和触发器。
为了进一步简化设置的任务,您可以使用 db2se_repl。这个工具能执行必要的 SQL 语句和复制命令,可用来创建表、视图及触发器,并可通过 asnclp 命令行接口发出必要的复制命令、执行复制功能。
