项目一:项目名称
项目简介(功能与用途):
某公司production system
项目难点与解决方案:
系统使用circular logging机制,同时客户的transaction都是比较小的,但是每次当运行crash recovery的时候需要45分钟。这个对客户来说是绝对不可接受的。
运行db2pd察看recovery进程发现
$ db2pd -database xxxxx -recovery
Database Partition 0 -- Database xxxxx -- Active -- Up 0 days
02:45:16
Recovery:
Recovery Status 0x00000C01
Current Log S0000000.LOG
Current LSN 0001224D595F
Job Type CRASH RECOVERY
Job ID 1
Job Start Time (1131047481) Thu Nov 3 xx:xx:xx xxxx
Job Description Crash Recovery
Invoker Type User
Total Phases 2
Current Phase 1
Progress:
Address PhaseNum Description StartTime
CompletedWork TotalWork
0x3129E460 1 Forward Thu Nov 3 13:51:21 2005
28950595 bytes 18446742022219551616 bytes
0x3129E558 2 Backward NotStarted 0
bytes 18446742022219551616 bytes
$
很明显TotalWork显示非正常数值。通过研究发现DB2程序中计算totalwork值时使用了非正确的算法,开APAR IY79320 修复错误
http://www-1.ibm.com/support/docview.wss?rs=71&context=SSEPGG&q1=IY79320&uid=swg1IY79320&loc=en_US&cs=utf-8&lang=en
同时与其他组员合作发现问题的根本原因发生在过大的历史文件,建议客户运行prune命令缩小220M的历史文件使得crash recovery速度恢复到2分钟左右。
项目成功与失败的经验归纳:
研究DB2代码基本可以解决90%以上来自客户的错误信息,但是对于优化问题研究代码则无能为力。
你在项目中岗位与贡献:问题分析者,开发小组与客户之间协调者
项目二:项目名称
项目简介(功能与用途):
某客户重要数据库从v7升级到v8在migrate database过程中发生错误,客户重新返回v7再次升级错误依旧。系统无法正常工作!
db2 migrate db xxxx
SQL10004C An I/O error occurred while accessing the database directory.
SQLSTATE=58031
项目难点与解决方法:
关键的难点在于错误信息并没有给出任何有效的提示,IO错误可以发生在任何地方,因此单纯地分析错误代码或者察看db2diag.log并不能够看到问题的所在。
首先我们要做的肯定是确认database catalog目录的完整性。
通过执行
Db2 list db directory
Db2 list db directory on <path>
我们可以测试出副本注册的数据库目录和当前路径下数据库目录的完整性。
通过测试发现第一条语句成功第二条语句失败。
很显然在升级NODE0000/sqldbdir目录时出现问题。
然后我们要做的不用说一定是db2trace,只要db2trace能够明显地看到第一条发生错误的函数调用我们就可以跟踪进入相应的db2源程序中发现当时正在运行的逻辑,同时找到问题的可能和解决方案。
正如我们的推断,db2trace的确显示问题发生在sqldbdir
由于上面的测试仅仅可以确认sqldbdir出现问题,但是并不能够保证数据库本身的完整性,因此我们还必须继续确认数据库的完整性。
通过db2trace db2 list db directory on <path>命令,格式化db2imdbd.dmp我们发现返回值为1000,通过对应的源程序发现这个返回值是说明数据库已经被successful migrated,因此我们就可以确认数据库自身没有问题。
在这里仅剩的最后一个问题就是怎样修复sqldbdir目录。
通过跟踪程序发现错误本身卡在fseek的C函数调用,每次调用后都会返回文件句柄丢失的错误。这里看起来相当奇怪,因为文件已经成功open并且read了header,所以最简单的方法就是手工升级目录。
在自己的测试环境切换到客户对应的fixpak level,然后让客户将每个分区下的sqldbdir目录发给我们,重新创建一模一样的路径然后自己进行db2 list db directory on <path>,这样db2在查询这个路径的时候如果发现文件格式还是v7的就会自动升级。
将升级后的文件发回给客户然后系统就可以成功运行。
项目成功与失败的经验归纳:
Db2trace可以跟踪到很多难以想象的细致的方面。通过trace一般来说可以找到相应的那一行C程序代码。通过分析源程序我们就可以相当确定某一个问题发生的所在和相应的解决方案,不必根据自己以往的经验来猜测客户可能遇到的问题。
你在项目中岗位与贡献:问题主要分析者,与开发小组和客户之间的协调者
项目三:项目名称
项目简介(功能与用途):
某公司执行db2move的时候,如果force applications all会使得db2move继续向DB2DBDFT所指定默认数据库下有着同样名称的表添加数据。
因此客户的默认数据库被测试数据库下的数据冲掉,只能恢复过去的备份数据。
项目难点与解决方法:
通过在测试环境下调试发现可以很轻易地重现问题。
重现方法:
建立数据库A
建立表T1,插入10000行数据,建立表T2,插入几行数据1,2,3
建立数据库B
建立表T1,T2
数据库A执行db2move export导出数据。
更改A数据库表T2,删除1,2,3,插入4,5,6
设置DB2DBDFT指向A
对B作db2move load replace,然后当import开始后执行force applications all杀掉load。
可以看到作为一个process运行的db2move无法被force applications 清除,force applications仅仅清除正在load的db2agent,因而db2move继续运行。但是现在数据库连接已经不存在了,因此db2move中的load API建立隐式连接,但是这个连接指向的却是default database。因此db2move继续向数据库A中的T2进行load,可以看到原本的4,5,6被清除,取而代之的则是1,2,3
问题的所在就是db2move的逻辑。对于force applications all和load api都是working as design。理论上force applications无法杀掉真正的process,因为db2move可能运行于client side……而load api确实是应该自动对default database进行连接,如果当前连接不存在。
因而我们需要对db2move的逻辑进行调整。
经过一段时间开发小组的讨论和研究,最终认为在db2move运行时disable DB2DBDFT参数,运行后自动恢复是一个唯一可行的方案 (曾经有人提出过每次load前判断连接是否存在,但是如果用户是在逻辑判定和真正的load之间的那一瞬间执行force application就会造成同样的问题)
不过后来由于考虑到db2 v9的db2move使用的是另一种架构,因而不存在这样的隐患,而这样的更改并不是在当初的设计基础上的,很有可能造成其他的未知错误。
最后客户同意将来更新到db2v9,所以问题的原因被查明,但是我们不打算再v8中修复这个错误。
开APAR JR23634(由于不打算实现所以并没有显示在IBM外部网站上)
项目成功与失败的经验归纳:
理解db2的运行逻辑和源程序逻辑是极为重要的。
单纯的理解上层的大致框架远远不能成为一个合格的技术支持专家,必须深入到源程序级别深入理解每一块细微的步骤才能在最大程度上对客户进行有效的支持。
你在项目中岗位与贡献:问题分析者,开发小组于客户之间协调者
项目简介(功能与用途):
某公司production system
项目难点与解决方案:
系统使用circular logging机制,同时客户的transaction都是比较小的,但是每次当运行crash recovery的时候需要45分钟。这个对客户来说是绝对不可接受的。
运行db2pd察看recovery进程发现
$ db2pd -database xxxxx -recovery
Database Partition 0 -- Database xxxxx -- Active -- Up 0 days
02:45:16
Recovery:
Recovery Status 0x00000C01
Current Log S0000000.LOG
Current LSN 0001224D595F
Job Type CRASH RECOVERY
Job ID 1
Job Start Time (1131047481) Thu Nov 3 xx:xx:xx xxxx
Job Description Crash Recovery
Invoker Type User
Total Phases 2
Current Phase 1
Progress:
Address PhaseNum Description StartTime
CompletedWork TotalWork
0x3129E460 1 Forward Thu Nov 3 13:51:21 2005
28950595 bytes 18446742022219551616 bytes
0x3129E558 2 Backward NotStarted 0
bytes 18446742022219551616 bytes
$
很明显TotalWork显示非正常数值。通过研究发现DB2程序中计算totalwork值时使用了非正确的算法,开APAR IY79320 修复错误
http://www-1.ibm.com/support/docview.wss?rs=71&context=SSEPGG&q1=IY79320&uid=swg1IY79320&loc=en_US&cs=utf-8&lang=en
同时与其他组员合作发现问题的根本原因发生在过大的历史文件,建议客户运行prune命令缩小220M的历史文件使得crash recovery速度恢复到2分钟左右。
项目成功与失败的经验归纳:
研究DB2代码基本可以解决90%以上来自客户的错误信息,但是对于优化问题研究代码则无能为力。
你在项目中岗位与贡献:问题分析者,开发小组与客户之间协调者
项目二:项目名称
项目简介(功能与用途):
某客户重要数据库从v7升级到v8在migrate database过程中发生错误,客户重新返回v7再次升级错误依旧。系统无法正常工作!
db2 migrate db xxxx
SQL10004C An I/O error occurred while accessing the database directory.
SQLSTATE=58031
项目难点与解决方法:
关键的难点在于错误信息并没有给出任何有效的提示,IO错误可以发生在任何地方,因此单纯地分析错误代码或者察看db2diag.log并不能够看到问题的所在。
首先我们要做的肯定是确认database catalog目录的完整性。
通过执行
Db2 list db directory
Db2 list db directory on <path>
我们可以测试出副本注册的数据库目录和当前路径下数据库目录的完整性。
通过测试发现第一条语句成功第二条语句失败。
很显然在升级NODE0000/sqldbdir目录时出现问题。
然后我们要做的不用说一定是db2trace,只要db2trace能够明显地看到第一条发生错误的函数调用我们就可以跟踪进入相应的db2源程序中发现当时正在运行的逻辑,同时找到问题的可能和解决方案。
正如我们的推断,db2trace的确显示问题发生在sqldbdir
由于上面的测试仅仅可以确认sqldbdir出现问题,但是并不能够保证数据库本身的完整性,因此我们还必须继续确认数据库的完整性。
通过db2trace db2 list db directory on <path>命令,格式化db2imdbd.dmp我们发现返回值为1000,通过对应的源程序发现这个返回值是说明数据库已经被successful migrated,因此我们就可以确认数据库自身没有问题。
在这里仅剩的最后一个问题就是怎样修复sqldbdir目录。
通过跟踪程序发现错误本身卡在fseek的C函数调用,每次调用后都会返回文件句柄丢失的错误。这里看起来相当奇怪,因为文件已经成功open并且read了header,所以最简单的方法就是手工升级目录。
在自己的测试环境切换到客户对应的fixpak level,然后让客户将每个分区下的sqldbdir目录发给我们,重新创建一模一样的路径然后自己进行db2 list db directory on <path>,这样db2在查询这个路径的时候如果发现文件格式还是v7的就会自动升级。
将升级后的文件发回给客户然后系统就可以成功运行。
项目成功与失败的经验归纳:
Db2trace可以跟踪到很多难以想象的细致的方面。通过trace一般来说可以找到相应的那一行C程序代码。通过分析源程序我们就可以相当确定某一个问题发生的所在和相应的解决方案,不必根据自己以往的经验来猜测客户可能遇到的问题。
你在项目中岗位与贡献:问题主要分析者,与开发小组和客户之间的协调者
项目三:项目名称
项目简介(功能与用途):
某公司执行db2move的时候,如果force applications all会使得db2move继续向DB2DBDFT所指定默认数据库下有着同样名称的表添加数据。
因此客户的默认数据库被测试数据库下的数据冲掉,只能恢复过去的备份数据。
项目难点与解决方法:
通过在测试环境下调试发现可以很轻易地重现问题。
重现方法:
建立数据库A
建立表T1,插入10000行数据,建立表T2,插入几行数据1,2,3
建立数据库B
建立表T1,T2
数据库A执行db2move export导出数据。
更改A数据库表T2,删除1,2,3,插入4,5,6
设置DB2DBDFT指向A
对B作db2move load replace,然后当import开始后执行force applications all杀掉load。
可以看到作为一个process运行的db2move无法被force applications 清除,force applications仅仅清除正在load的db2agent,因而db2move继续运行。但是现在数据库连接已经不存在了,因此db2move中的load API建立隐式连接,但是这个连接指向的却是default database。因此db2move继续向数据库A中的T2进行load,可以看到原本的4,5,6被清除,取而代之的则是1,2,3
问题的所在就是db2move的逻辑。对于force applications all和load api都是working as design。理论上force applications无法杀掉真正的process,因为db2move可能运行于client side……而load api确实是应该自动对default database进行连接,如果当前连接不存在。
因而我们需要对db2move的逻辑进行调整。
经过一段时间开发小组的讨论和研究,最终认为在db2move运行时disable DB2DBDFT参数,运行后自动恢复是一个唯一可行的方案 (曾经有人提出过每次load前判断连接是否存在,但是如果用户是在逻辑判定和真正的load之间的那一瞬间执行force application就会造成同样的问题)
不过后来由于考虑到db2 v9的db2move使用的是另一种架构,因而不存在这样的隐患,而这样的更改并不是在当初的设计基础上的,很有可能造成其他的未知错误。
最后客户同意将来更新到db2v9,所以问题的原因被查明,但是我们不打算再v8中修复这个错误。
开APAR JR23634(由于不打算实现所以并没有显示在IBM外部网站上)
项目成功与失败的经验归纳:
理解db2的运行逻辑和源程序逻辑是极为重要的。
单纯的理解上层的大致框架远远不能成为一个合格的技术支持专家,必须深入到源程序级别深入理解每一块细微的步骤才能在最大程度上对客户进行有效的支持。
你在项目中岗位与贡献:问题分析者,开发小组于客户之间协调者