简介: 本文讨论和分析在常见的 DB2 远程 SQL 复制应用场景中经常遇到的错误和原因,以及处理方式。通过深入分析和刨析 SQL 复制的运行机制,以及列举出常见错误的处理方法,使 db2 开发和管理人员能更深入的了解 DB2 SQL 复制的特性,缩短他们处理问题的时间,提高他们在系统中应用 SQL 复制的效率。
DB2 的 SQL 复制为用户提供了图形操作界面,用户可以通过相应的指引很容易的建立数据的复制关系。但是光依靠图形界面很难全面地了解 SQL 复制内部的运行机制和运行状态,遇到问题的时候常常会感觉无从下手。本文针对哪有对 SQL 复制有了初步知识的读者,重点讨论 SQL 复制运行的过程当中经常碰到的问题,并通过一些实际应用中遇到的问题,探讨如何事先避免以及问题发生之后的解决办法。
DB2 有两种在表与表之间复制数据的技术:SQL 复制和 Q 复制。他们各有其适合的应用领域及特点。SQL 复制是其中发展比较成熟的一种技术,再加上它不需要其它软件的配合,可以支持不同类型的数据库与 DB2 之间的数据同步,因此适用的范围比较广。与之相比,Q 复制在性能上优势比较明显。
简单来说,DB2 远程 SQL 复制就是通过 Capture 程序提取出对数据源表的修改 , 并把它保存在 CD 表中 , 再由 Apply 程序读取这些修改,进而应用到目标数据表以完成数据复制。
总体上来说,可以把 DB2 复制服务系统分为以下四个组件:
- DB2 复制中心 (Replication Center)
- Capture 程序(有时需要 triggers)
- Apply 程序
- 监视器程序
以上这些组件各自独立运行,它们之间通过存储和修改在 DB2 复制控制表 (control tables) 中的记录相互通讯。DB2 复制中心是一个拥有图形化界面的管理工具,用户可以通过它进行数据复制关系的管理,进行包括数据源的注册 (registered tables),订阅集 (subscription sets) 和报警条件等的设置。复制中心根据用户的设置生成相应的 SQL 脚本 , 并运行该脚本以对复制控制表进行修改。Capture 程序会访问复制控制表,读取数据源表的注册信息,根据注册信息从 DB2 日志文件中提取出数据源表的修改,并且修改复制控制表,标明目前运行的状态。Apply 程序也会访问复制控制表,得到目前的数据源的变动情况,并把修改应用到目的表上,再修改复制控制表,标明 Apply 程序的运行状况。监视器程序根据 Capture 程序和 Apply 程序对复制控制表的修改来了解当前系统的运行情况和存在的问题,再根据用户对报警的设置发出相应的警报。更详细的复制过程和原理,这里就不做详细地介绍了,但是对复制过程的细节了解的越多,用户就能更顺利地解决复制当中出现的问题。如果对这些内容感兴趣,也可以参考下面的资料。
对于如何设置一个远程 SQL 复制,已经有很多文章详细讨论过了。如果你对这些过程有任何问题,可以看一看下面的参考资料。在这里,我们只选取其中很少有人关注过的话题进行讨论。
1、制定复制计划
在一个正式的生产环境中,部署数据复制需要先制定复制计划。开始整个复制系统的部署之前,要首先完成这个步骤,这样有助于帮助规划人员或者 DBA 更有效率和全面的部署复制系统。根据复制数据量的规模和表的数量,你可能需要考虑下面的问题,然后根据答案来确定合适的复制计划:
- 计算 Capture 和 Apply 程序需要的内存数量,用以决定是否需要设置 memory_limit 参数。
- 系统中会有哪些表和表上的哪些列需要被复制?
- 指定 CD 和 UOW 表所在的表空间的名字。通常,给 CD 表单独的表空间是一个好的设计。
- CD 和 UOW 表空间需要多少的初始化空间?这个问题跟系统数据的变动量密切相关。
- 为 CD 表和目的表制定一个命名规范。为以后的统一管理创造方便。
- Capture 控制表和 Apply 控制表所在的表空间是什么?通常他们也应该有一个单独的表空间。
- 系统的订阅集可能会有多少,为其定义一个命名规范
- 为避免数据积累的太大,要制定剪裁计划。如删除多少天前的 IBMSNAP_APPLYTRACE 和 IBMSNAP_APPLYTRAIL 数据
- 根据系统同步的数据量的大小,决定是否启用自动同步,是否需要修改 ASNLOAD 用户出口程序。如果启动自动同步,需要在 Apply 程序的运行目录留出足够的空间来容纳 export 文件。
- 规划 Apply, Capture 程序的运行位置和密码文件的位置,要给日志文件和可能的溢出文件保留足够的空间。
2、设置数据复制的概要文件
用户在使用复制中心设置数据的复制关系的时候,系统需要生成一些新的对象,比如目的表,CD 表,索引以及所用到的表空间等等。对于这些对象,系统会有一个默认值,比如 CD 表的名字会以 CD 加源表名来代替。如果用户自己设定了一个不同的命名规范,每次的操作就都需要修改这些名字。数据复制的概要文件就是为了让用户更轻松的执行数据复制的操作。用户可以通过修改概要文件来符合自己的习惯或者命名规范。DB2 提供了下面三个层次的概要文件:
- 控制表概要文件
- 数据源概要文件
- 目标对象概要文件
对于上面的概要文件,用户可以指定他们所涉及对象的缺省值,包括它们的命名规则,一些属性值等等。当你进行相应的操作时,这些值会作为缺省值出现,用户可以接受,也可以修改它们。对于这三种概要文件,用户可以通过以下方式调出它们的修改窗口:
- 打开 DB2 Replication Center
- 在左视图中展开 SQL Replication
- 鼠标右键点击 Definitions,会出现三个管理概要文件的菜单
- 选择其中一个,在弹出的管理窗口进行设置。
3、控制表的数据清理
在 SQL 数据复制系统中,一些控制表的数据是不断累积的,它们的尺寸会不断变大。如果不能及时的清理这些数据,就可能会对系统性能甚至正常运行造成影响。这里主要想讨论 CD 表,UOW 表,IBMSNAP_APPLYTRACE 表和 IBMSNAP_APPLYTRAIL 表。
CD 表和 UOW 表中记录着所有源表的数据变动,它们会增长的很快。Capture 程序负责定期清理其中无用的数据,但这取决于 IBMSNAP_PRUNE_SET 表中的 SYNCHPOINT 列。正常的清理过程要比较一个数据源所对应的所有订阅集,取其中最小的一个同步点 (SYNCHPOINT),清除这以前的数据。因为它确保了清除掉的数据已经完全发布到了所有的订阅集。也正是因为这一点,用户在停用某一个订阅集或者设置 Apply 程序的运行频率的时候要非常的小心,如果时间过长,就可能导致 CD 表和 UOW 表中的数据积累过大,影响系统运行的效率。SQL 数据复制系统为了避免这种情况,设置了一个保留极限(retention limit),如果表中的数据超过这个极限(缺省是 1 周),Capture 程序就会把超过期限的数据删除。这时如果订阅集被重新激活,就需要一个全刷新。
另外,控制表 IBMSNAP_APPLYTRACE 和 IBMSNAP_APPLYTRAIL 里保存着 Apply 程序执行时候的一些历史记录,如果有一些订阅集复制失败,这两个表中就会被填入相应的内容。用户应该编写程序自动的清理这两个表,否则他们会逐渐变大,直到填满整个表空间,那是就会影响到 SQL 复制系统的正常功能了。另外一种更简单的方法是,用户可以在某一个订阅集中定义一个 After-SQL 来删除这两个表某一个时间以前的数据。
这一章介绍 SQL 复制常用的一些命令,以及到哪里能查询到它的运行日志。对于 SQL 复制系统的三个组件,都各自对应两个命令,一个是启动命令,另一个是当组件运行的时候操作组件运行方式的命令。
Capture 程序:asncap 和 asnccmd
asncap capture_server=db capture_schema=ASN capture_path=/ db2/asn/capture/logs pwdfile=asnpwd.aut startmode=warmns asnccmd capture_server=db capture_schema=ASN reinit |
Apply 程序:asnapply 和 asnacmd
asnapply apply_qual=DB_QUAL control_server=db apply_path=/db2/asn/apply/logs pwdfile= asnpwd.aut asnacmd apply_qual=DB_QUAL control_server=db status |
监视程序:asnmon 和 asnmcmd
asnmon monitor_server=db monitor_qual=DB_MON monitor_interval=120 |
另外还有两个命令,可以组合起来用来修复源表和目的表中不一致的记录:asntdiff 和 asntrep
asntdiff DB=apply_db schema=asn where="set_name = 'my_set' and target_table = 'table_name'" diff=diff_table asntrep DB=apply_db SCHEMA=asn WHERE="set_name = 'my_set' and target_table = 'table_name'" diff=diff_table |
在上面的命令行调用的时候,用到了一个密码文件 asnpwd.aut。这个文件里存储着 Capture 或者 Apply 程序会用到的数据库名字和对应的链接用户名和密码。DB2 也提供了一个命令行工具来生成和编辑这个文件:asnpwd
asnpwd INIT ENCRYPT PASSWORD asnpwd ADD ALIAS db ID dbuser PASSWORD dbpasswd using /db2/asn/capture/logs/asnpwd.aut |
这三个组件在启动的时候都会有各自的参数指定它们运行的工作目录:capture_path,apply_path 和 monitor_path。用户可以在这些目录中发现它们的日志文件。它们记录的信息可以帮助用户判断系统是否运行正常。另外在控制表 IBMSNAP_APPLYTRACE 和 IBMSNAP_APPLYTRAIL 中也记录着 Apply 程序在运行时产生的错误。
上述的命令和日志信息可以帮助用户判断系统可能存在的问题。用户也可以用下面的 SQL 来判断目前是否存在有问题的表复制:
db2 "select b.TARGET_OWNER,b.TARGET_TABLE, a.APPLY_QUAL,a.SET_NAME, a.activate, a.status, a.lastsuccess from ASN.IBMSNAP_SUBS_SET a, asn.ibmsnap_subs_membr b where a.apply_qual=b.apply_qual and a.set_name=b.set_name and b.TARGET_TABLE='%table%' and b.TARGET_OWNER='%owner%' and a.status != 0 with ur " |
如果上面的 SQL 返回了结果,说明这些复制关系存在问题。需要采取措施进行检查和排除。
下面是一些在实际的应用中经常会遇到的错误,当你使用上一章所介绍方法发现目前某一个表复制出现错误,就可以采用下面的方法进行检查和排除错误。
通常我们通过 Capture 程序日志来诊断各种 Capture 错误。Capture 日志位于 Capture Path 目录下,文件名类似于:db2inst1.DBNAME.ASN.CAP.log
问题 1:
来源于 Capture 日志:
2010-03-05-10.50.07.456459 ASN0071E CAPTURE "ASN" : "WorkerThread". The data type attribute of the column "ID" in the CD table "CD"."STAFF" is not compatible with the data type attribute of the corresponding source column. 2010-03-05-10.50.07.456629 ASN0189I CAPTURE "ASN" : "WorkerThread". The Capture 程序 is terminating because an error occurred for registered table "TEST1. STAFF" and the registration is configured to stop on error. |
分析:
由于数据源表发生的变化,导致 CD 表的列与数据源表的列属性不一致。
解决方法:
重新注册该数据源表,生成正确的 CD 表。然后启动 Capture。
问题 2:
来源于 Capture 日志:
2010-02-03-05.27.30.585586 ASN0144E CAPTURE "ASN" : "WorkerThread". The program detected that the source database "SDB" has been restored or rolled forward. A cold start is recommended to restore consistency. |
分析:
因为数据库是通过 restore 方式重建的。所以如果使用 warmns 模式启动 Capture 程序,会得到提示,Capture 程序需要一次 cold 启动。
解决方法:
可以使用 cold 方式启动 Capture 程序。但是需要对所有的 apply set 进行完全刷新。
也可以再次使用 warmns 模式启动 Capture 程序。就会成功。这只是一个 warning,并不要求必须使用 cold 模式启动。
问题 3:
来源于 Capture 日志:
2010-02-03-11.10.12.050721 ASN8041D "Capture" : "ASN" : "WorkerThread" : db2LogRead API is sending us backwards in the DB2 Log: First LSN is "0000:0000:00ac:d1db:43ba" while Next Start LSN is "0000:0000:0000:0000:0000" 2010-02-03-11.10.12.050815 ASN0005E CAPTURE "ASN" : "WorkerThread". The Capture program encountered an error when reading the DB2 log. The log sequence number is "0000:0000:00AC:D1DB:43BA", the SQLCODE is "-2656", and the reason code is "". |
分析:
启动 Capture 程序所需的日志文件无法读取。
解决方法:
运行 db2flsn(SQLLOGCTL.LFH) 获取 Capture 程序所需的日志文件。拷贝所需日志文件到 active log 目录。例如,
db2flsn 00ACD1DB43BA Given LSN is contained in log page 10645 in log file S0003020.LOG. |
问题 4:
来源于 Capture 日志:
2009-02-24-05.00.16.067538 ASN0596I "Capture" : "ASN" : "Initial" The program could not create an IPC queue with keys "[NOT SET]" for path "/db2/tmpdir/db2inst1/db2inst1.SDB.ASN.CAP.IPC". OSSE reason is "Invalid parameter". 2009-02-24-05.00.16.067589 ASN0507E "Capture" : "ASN" : "Initial" : The program could not create the replication communications message queue. |
分析:
通过日志解析我们能得出错误与 IPC queue 相关。很有可能是 tmpdir 路径不正确。
解决方法:
检查 tmpdir 路径。其他相关的 IPC queue 问题。可能需要我们清除旧的 IPC 信息。我们可以使用 ipcrm – m/q/s。
通常我们通过查看 Apply 程序日志和 Apply Trace 文件来诊断各种 Apply 错误。Apply 程序日志相对来说比较简单,但是提炼了最重要的错误提示。Apply Trace 文件的信息比较详尽,我们可以看到各种具体的参数,包括数据源表和目的表的对应信息。在问题 2 的描述中,给出了一段比较详细的 Apply Trace 文件的例子。Apply 程序日志位于 Apply Path 目录下,文件名类似于:db2inst1.DBNAME.apply_qual. APP.log。Apply Trace 文件也位于相同目录,文件名类似于:apply_qual.TRC。
问题 1:
来源于 Apply 程序日志:
2010-02-07-20.54.05.980738 ASN1003E APPLY "MY_APPLY_Q1" : "WorkerThread". The Apply program could not connect to the server "SDB". |
分析:
Apply 程序不能连接到源数据库。
解决方法:
检测目的数据库到源数据库的连通性。可能是网络问题,也可能是用户名和密码问题,还可能是 catalog 问题。对症下药即可。
问题 2:
来源于 Apply 程序日志:
2010-03-12-03.15.46.981797 ASN1016I APPLY "MY_APPLY_Q1" : "WorkerThread". Refresh copying has been disabled. The error code is "5E1603". |
检查 Apply Trace 文件:
WPLAN: Set is skipped. apperrc is 5E1603. SAT: ASNLOAD = N, EFFECT_MEMBERS = 0 SAT: FULL_REFRESH = N SAT: SET_INSERTED = 0 SAT: SET_DELETED = 0 SAT: SET_UPDATED = 0 SAT: SET_REWORKED = 0 SAT: SET_REJECTED_TRXS = 0 SAT: STATUS = -1 SAT: LASTRUN = 2010-03-12-00.33.46.156139 SAT: LASTSUCCESS is null SAT: SYNCHPOINT is null SAT: SYNCHTIME is null SAT: SOURCE_ALIAS is SDB SAT: SOURCE_SERVER is SDB SAT: SOURCE_OWNER is TEST1 SAT: SOURCE_TABLE is STAFF SAT: TARGET_ALIAS is TDB SAT: TARGET_SERVER is TDB SAT: TARGET_OWNER is TEST2 SAT: TARGET_TABLE is STAFF SAT: SQLSTATE is null SAT: SQLERRM is null SAT: SQLCODE is null SAT: SQLERRP is null SAT: APPERRM is ASN1016I APPLY "MY_APPLY_Q1" : "WorkerThread". Refresh copying has been disabled. The error code is "5E1603". |
分析:
通常是由于在需要进行完全刷新的时候,数据源表的“允许目标表完全刷新”标志未选中而造成的。
解决方法:
通过 Apply Trace 文件的具体信息,对相应的目标表进行手工完全刷新即可。
问题 3:
来源于 Apply 程序日志:
2010-03-03-01.13.22.362826 ASN1001E APPLY "MY_APPLY_Q1" : "WorkerThread". The Apply program encountered an SQL error. The ERRCODE is "BC0103". The SQLSTATE is "57011". The SQLCODE is "-964". The SQLERRM is "". The SQLERRP is "SQLRI03B". The server name is "". The table name is ""ASN".IBMSNAP_PRUNE_SET". |
Apply Trace 文件:
*** SQL ERROR ***: SQL0964C The transaction log for the database is full. SQLSTATE=57011 |
分析:
结合 Apply 程序日志和 Trace 文件。我们不难看出错误的原因是 transaction log 满的原因。
解决方法:
如果是其他大作业造成的 transaction log 满,我们可以等待大作业的提交或者回滚。如果 replication 就是造成问题的大作业,而且没有办法立刻扩充 transaction log,使用针对目的表的完全刷新,应该是不错的选择。
总的说来,出现 SQLSTATE 57011 的错误的时候,我们考察的重点要放在 file system full 上,检查数据库相关的目录:活动日志目录、表空间、实例目录等等,来解决问题。
问题 4:
来源于 Apply Trace 文件:
SAT: APPERRM is ASN1022E "MY_APPLY_Q1" : "WorkerThread": "". The Apply program cannot write to the work file "/db2rep/MY_APPLY_Q1/MY_APPLY_Q1.000" because of a system error with ERRNO "28". The error code is "932203". … SAT: APPERRM is ASN1024E "MY_APPLY_Q1" : "WorkerThread": "". The Apply program cannot close the work file "/db2rep/MY_APPLY_Q1/MY_APPLY_Q1.000" because of a system error with ERRNO "28". The error code is "932404". |
分析:
在 Apply Trace 文件中,我们可以发现溢出文件的存在,同时看到了 system error 28,这个错误表示当前设备空间不足。因此,我们需要检查 Apply 程序工作目录是否满。
解决方法:
如果溢出文件致使 Apply 程序工作目录满,则可考虑临时修改 Apply 程序工作目录的方法。也可以考虑目标表完全刷新的方式。
问题 5:
来源于 Apply 程序日志:
2010-03-05-11.53.33.237886 ASN1001E APPLY "MY_APPLY_Q1" : "WorkerThread". The Apply program encountered an SQL error. The ERRCODE is "C80105". The SQLSTATE is "57016". The SQLCODE is "-668". The SQLERRM is "TEST2.PROJECT". The SQLERRP is "SQLDTBLR". The server name is "". The table name is "PROJECT". |
检查 Apply Trace 文件:
*** SQL ERROR ***: SQL0668N Operation not allowed for reason code "7" on table "TEST2.PROJECT". SQLSTATE=57016 |
分析:
通过日志,我们可以得到错误与表 TEST2.PROJECT 相关。察看表的状态,处于 reorg pending。由于目标表的不可操作性,导致了 Apply 程序的失败。
解决方法:
reorg 目的表,解除表的不可操作状态。Apply 程序就能恢复正常。
出现 The SQLCODE is "-668"的错误的时候,有时候,不一定是目的表本身,依赖于目的表的 Materialized Query Table 失效,也会使 Apply 程序失败。
问题 6:
来源于 Apply Trace 文件:
BLDDEL: Prepared delete stmt is DELETE FROM "TEST2"."PROJECT" WHERE "PROJNO" = ? AND "DEPTNO"= ? . BLDDEL: Prepare delete failed. apperrc is 7A0102. sqlstate is 56098. sqlcode is -727 … *** SQL ERROR ***: SQL0727N An error occurred during implicit system action type "7". Information returned for the error includes SQLCODE "-551", SQLSTATE "42501" and message tokens "TEST2|ALTER TABLE|TEST2.PROJECT". LINE NUMBER=0. SQLSTATE=56098 |
分析:
通过 Trace 文件的分析,我们知道是目的表删除数据的时候出现了错误。但是目的表状态正常。通过察看数据库 invalid 和 inoperative 对象,我们发现了处于 inoperative 的 trigger。而这些 trigger 依赖于目的表。如果删除目的表的数据,就会触发这些触发器。
解决方法:
重建处于 inoperative 的 trigger 即可。问题 5 和问题 6 都告诉我们要关注依赖于目的对象的各种 objects 的状态。
问题 7:
来源于 Apply 程序日志:
2010-03-17-23.21.29.703458 ASN0999E "Apply" : "MY_APPLY_Q1" : "WorkerThread" : Error condition "constriant violation error,refer to applytrail table for detail", error code(s): " ", " ", " ". |
检查 Apply Trace 文件:
*** SQL ERROR ***: SQL0532N A parent row cannot be deleted because the relationship "TEST2.TABLE_C.TABLE_C_FK" restricts the deletion. SQLSTATE=23504 |
分析:
这里的错误与外键约束相关。在这个示例中,存在外键约束的 2 个表同时被复制,而且,2 个目标表保留了同样的约束关系。错误发生于 delete 操作。在数据源表中,正确的删除次序为:
删除子表中与父表存在关联关系的行;
删除父表中的行;
如果在 apply 运行个过程中,apply 试图尝试先删除父表中的行,就会报错。
外键约束关系如下:
ALTER TABLE TEST2.TABLE_C ADD CONSTRAINT TABLE_C_FK FOREIGN KEY (CODE,APPL_CODE) REFERENCES TEST2.TABLE_P (CODE,APPL_CODE) ON DELETE NO ACTION ON UPDATE NO ACTION |
解决方法:
这样的错误,通常可以忽略,会自动解决。在 Apply 程序尝试先删除父表中的行失败后,Apply 程序仍会成功删除子表中的数据;当 Apply 程序再次运行时,就能成功删除父表中的数据了。
或者我们可以去掉目的表之间的外键约束关系,因为我们可以凭借数据源表来保持这样的约束关系。
总体来说 SQL 复制是一个比较稳定的系统,但也会需要人为的干涉进行不断地维护。详细地了解它底层的一些运作规律会有助于用户更顺利地解决问题。希望我们在这里提供的一些方法和案例能对您的维护工作有所帮助。
原文链接:http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-1007huangxp/index.html