在使用DB2数据库的过程中,发生一些这样或那样的问题和故障是不可避免的。在发生这些问题之后,如何及时和准确地找到故障原因并合理地处理这些问题就显得极为重要。本章介绍在DB2中的一些高级诊断工具和诊断方法。快速、合理地使用这些工具能够极大地提高DBA处理数据库故障的能力和效率。
本章介绍的工具有db2dart和inspect、db2pdcfg、db2trc、db2_call_stack和db2nstck,并结合这些工具给出了大量的诊断问题的实例。
本章主要讲解如下内容:
● db2dart和inspect
● db2pdcfg
● db2trc
● db2_call_stack和db2nstck
9.1 db2dart和inspect
9.1.1 db2dart和inspect概述
当DB2数据库出现异常后,可以使用db2dart或inspect命令查看整个数据库的一致性。db2dart命令可以用来验证数据库以及相关的数据库对象是否正确,是否存在问题;还可以用来显示数据库控制文件的内容,以便在重建数据库时从其他情况下无法访问的表中抽取数据。
如果想查看使用db2dart命令的相关语法,可以在当前DB2 CLP窗口中,执行db2dart命令(不带任何参数),就可以看到其相关选项了。db2dart的基本语法是“db2dart < database name > [ action ] [ options . . . ] ”,默认情况下,db2dart实用程序将创建一个“数据库名.RPT”的报告文件。db2dart实用程序直接从磁盘中读取数据库中的数据和元数据,而不是通过DB2数据库管理器来进行访问。
使用db2dart实用程序时,需要注意,要保证该数据库上没有活动的数据库连接(也就是说如果不取消激活数据库,那么db2dart将产生不可靠的结果)。如果您在当前DB2 CLP窗口中,先连接示例数据库SAMPLE,然后再执行“db2dart sample /db”命令,那么会有FYI提示信息,告诉你现在SAMPLE数据库上有一个活动的连接,请停掉所有的连接后再次执行db2dart命令,具体过程和提示信息如下所示:
C:\> db2 connect to sample 数据库连接信息
数据库服务器 = DB2 / NT 9.5.0
SQL 授权标识 = DB2ADMIN
本地数据库别名 = SAMPLE
C:\> db2dart sample /db
FYI: An active connection to the database has been detected .
False errors may be reported .
Deactivate all connections and re-run to verify .
Warning : The database state is not consistent .
Warning : Errors reported about reorg rows may
be due to the inconsistent state of the database .
DB2DARTDB2DART Processing completed with warning ( s ) !
Complete DB2DARTDB2DART report found in :
C:\DOCUME~1\ALLUSE~1\APPLIC~1\IBM\DB2\DB2COPY1\DB2\DART0000\SAMPLE.RPT
遇到这种情况,正确的做法是在当前DB2CLP窗口中,发出“force applications all”命令,断开所有的数据库连接,然后执行“db2dart sample /db”命令,具体过程如下所示:
C:\> db2 force applications all
DB20000I FORCE APPLICATION 命令成功完成。
DB21024I 此命令为异步的,可能未能立即生效。
C:\> db2 list applications
SQL1611W “数据库系统监视器”没有返回任何数据。
C:\> db2dart sample /db
The requested DB2DART processing has completed successfully!
Complete DB2DART report found in:
:\DOCUME~1\ALLUSE~1\APPLIC~1\IBM\DB2\DB2COPY1\DB2\DART0000\SAMPLE.RPT
db2dart命令成功完成,db2dart执行结果显示正常,如果有错误的话,会提示有ERROR存在,所有的结果都会存储在SAMPLE.RPT中。打开SAMPLE.RPT文件,可以看到数据库诊断的详细信息,由于篇幅有限,这里只列示了部分信息,如下所示:
DART (V9.5) Report :
2008-04-02-23.28.24.531000
Database Name : SAMPLE
Report name : SAMPLE.RPT
Old report back-up : SAMPLE.BAK
Database Subdirectory : C:\DB2\NODE0000\SQL00002
Operational Mode : Database Inspection Only ( INSPECT )
Action option : DB
Connecting to Buffer Pool Services . . .
Database inspection phase start .
Tablespace file inspection phase start .
Loading tablespace files .
Inspecting next tablespace and associated containers .
Inspecting next tablespace and associated containers .
Inspecting next tablespace and associated containers .
Inspecting next tablespace and associated containers .
Inspecting next tablespace and associated containers .
Inspecting next tablespace and associated containers .
Inspecting next tablespace and associated containers .
7 tablespaces were identified and their containers checked .
Tablespace file inspection phase end .
SYSBOOT inspection phase start .
Data inspection phase start . Data obj : 1 In pool : 0
Data inspection phase end .
SYSBOOT inspection phase end .
SYSTABLES inspection phase start .
Data inspection phase start . Data obj : 5 In pool : 0
Data inspection phase end .
SYSTABLES inspection phase end .
Bufferpool file report phase start .
1 bufferpools were identified .
Bufferpool file report phase end .
Tablespace inspection phase start . Pool : 0
Tablespace-info inspection phase start .
Checking Table space ID : 0
Name = SYSCATSPACE
Extent size = 4
# of containers = 1
----------------略----------------------------
Table inspection end .
Tablespace inspection phase end .
Tablespace inspection phase start . Pool : 6
This is a temporary table space . Nothing to inspect .
Tablespace inspection phase end .
Database inspection phase end .
----------------略----------------------------
我们在数据库的日常维护过程中,经常使用的 db2dart命令的选项主要有:
● /DB (默认值):检查整个数据库。
● /T:检查单个表。
● /TSF:只检查表空间文件和容器。
● /TSC:检查一个表空间的结构,但不包含它所属的那些表。
● /TS:检查一个单独的表空间和它所属的那些表。
● /DI:转储(DUMP)索引页结构。
下面我们举几个使用 db2dart和inspect的案例。
9.1.2 利用db2dart查找停顿(quiesce)表空间的用户
在我们执行quiesce命令停顿一张表期间,该表所在的表空间无法被其他应用访问,要查找停顿表空间的用户,我们可以使用DB2 LIST TABLESPACES SHOW DETAIL命令。下面借助 db2dart工具产生的报告,我们可以查询到发出quiesce命令的原始用户。具体执行步骤如下:
(1) 停止DB2实例:db2stop force。
(2) 产生db2dart的报告:db2dart sample /dtsf。
(3) 从报告中查找发出停顿命令的用户:根据命令执行结果的提示,找到db2dart产生的报告文件。打开该文件,对于停顿的表空间,可以在文件中找到信息如下所示:
Information for Tablespace ID: 2
-------------------------------------
Tablespace name: USERSPACE1
Table space flags (HEX): 0101
Table space type: System Managed Space (SMS)
Page size: 4096
Extent size: 32
Prefetch size: 32
Version: 9
Tablespace state: 2
Number of quiescers: 1
Userid of quiescer: DB2INST1
Quiesce state: 2——注:16进制表示的表空间状态,可执行db2tbst 0x2命令查看16进制
的表空间状态的详细描述,命令输出结果:Quiesced Update
Tbspace ID of quiesced object: 2——注:表空间ID,对应SYSCAT.TABLES表中的
TBSPACEID Table ID of quiesced object: 15——注:表ID,对应SYSCAT.TABLES表中
的TABLEID字段
EDU ID: 0
......
定位表空间的ID和表的ID后,执行下面的SQL语句找出是哪个表:
db2 select tabname from syscat.tables where tbspaceid=2 and tableid=15
TABNAME
------------------------------------------------------------------------
STAFF
1 条记录已选择。
使用查找到的用户DB2INST1登录后,执行重置命令:
db2 quiesce tablespaces for table db2inst1.staff reset
命令执行成功后连接数据库,验证表空间状态正常。
9.1.3 db2dart诊断高水位问题
我们在本书的第4章给大家讲过表空间高水位的概念,现在让我们来讨论一个实际生产中有关高水位的案例。
如果在一个表空间中删除了大量记录和表后,尝试缩小表空间大小以释放更多空间,那么会产生什么样的结果呢?下面让我们查看一下执行这个操作产生的问题诊断信息。当对这个表空间中的表执行完reorg命令后,用调整表空间命令(alter tablespace)缩小表空间失败,返回错误SQL20170N(表空间中没有足够的空间来执行指定的操作)。具体信息如下所示:
alter tablespace tbspace1 resize "(all 15000k)"
DB21034E The command was processed as an SQL statement because it was not a valid Command Line Processor command. During SQL processing it returned:
SQL20170N There is not enough space in the table space "TBSPACE1 " for the specified action. SQLSTATE=57059
为什么缩小表空间大小会失败呢?
失败原因
在这个案例中,由于表空间缩小的空间大小大于在高水位标记之上的空间大小,因此调整表空间(alter tablespace)命令失败并且返回SQL20170N错误码。通常,你可以通过执行reorg table命令来释放被占用的扩展数据块,这样就可以降低表空间的高水位标记;但是如果高水位标记被空间映射页(SMP)持有,那么扩展数据块将不能被reorg命令移动。这个操作(reorg)或许就不能成功地降低高水位标记。
当执行reorg table命令时,如果满足下面的任何条件,那么都不能降低高水位标记:
● 高水位标记位置是表的PAGE 0页(一个表对象的开始页)。
● 内部页面管理页在高水位标记位置,如SMP(空间映射页)或者EMP(扩展数据块映射页)。
● 执行一个表的在线(ONLINE)重组并且未指定临时表空间。这个重组表操作将导致更高的高水位,并且表不能重新覆盖原来的位置。
● 由于重组后必须要进行索引集群,所以变长数据记录可能导致更差的页面填写。填写数据结果将导致表占用空间反而比reorg之前有所增加,也就是说高水位标记将升高而非下降。
问题总结
当我们看到某个DMS表空间的已用页数低于高水位标记时,则有可能通过如下方法降低高水位标记:
● 重组表空间中的某个表。
● 将某个表中的数据导出,然后将它删除,重新创建该表再将数据导入。
在以上的方法中,首先要找到持有高水位标记的那个表,这可以通过db2dart命令(在停止实例后方可使用)加上/DHWM选项,然后从命令所产生的报告文件中来获得相关信息。
首先要找到持有高水位标记的那个表,执行db2dart命令:
db2dart sample /dhwm /tsi 2 /rptn DLHW.TXT
查看db2dart的输出文件DLHW.TXT,查看持有高水准标记的表对象的信息:
Dump highwater mark processing -phase start.
Number of free extents below highwater mark: 168
Number of used extents below highwater mark: 139
Object holding highwater mark:Object ID: 4
Type: Table Data ExtentDump highwater mark processing -phase end.
执行下面的SQL语句找出具体是哪个表持有高水位标记:
select tabschema, tabname from syscat.tables where tableid = 4 and tbspaceid=2
而要获得对该表执行哪些操作可降低HWM的建议,可执行db2dart命令并且加上/LHWM选项,这样就可以从产生的报告文件中获得相关信息。使用/LHWM选项时,要求用户给出表空间的标识以及希望HWM降低到的页数(虽然不能保证HWM一定能降低到这一用户期望值),如果该值使用0,则表明由DB2将HWM降低到能够达到的最低值。如下所示:
db2dart sample /lhwm /tsi 8 /rptn lhwm.txt
执行db2dart/lhwm命令,查看建议信息:
Lower highwater mark processing -phase start.
Current highwater mark: 306Desired highwater mark: 124
Number of used extents in tablespace: 139
Number of free extents below original HWM: 168
Number of free extents below desired HWM: 122
Number of free extents below current HWM: 168
Step #1: Object ID = 4=> Offline REORG of this table using the LONGLOBDATA option (do not specify a temporary tablespace).
Table: DB2ADMIN.HIST1
在上面的例子中,我们可以通过对表DB2ADMIN.HIST1做离线重组来降低高水位。另外还可利用db2dart加/RHWM选项来移去DMS表空间中不再需要的空间映射数据块来降低HWM,这些空间映射数据块在其映射的数据被删除时是不会被删除的。例如,如果高水位标记被一个不可挪动的空间映射页(SMP)扩展数据块持有,那么我们可以使用下面的命令来降低表空间的高水位标记:
db2dart sample/tsi 2/np 0/rhwm --注:选项/np 0会使高水位标记降至尽可能低的位置
db2dart命令可以被用于在数据库停止的情况下移动那些SMP扩展数据块。
注意:
如果是可恢复数据库(采用归档日志),那么在执行完此操作后数据库将被置于备份暂挂状态。这是因为db2dart不产生任何重做日志。因此,在执行完db2dart命令后必须对数据库做一个全备份操作。
9.1.4 db2dart诊断数据页损坏问题
下面我们讨论一个实际的案例,请看下面的db2diag.log文件:
2008-09-22-11.46.45.864000+480 I805726H366 LEVEL: Error
PID : 1860 TID : 2732 PROC : db2syscs.exe
INSTANCE: DB2INST NODE : 000
FUNCTION: DB2 UDB, buffer pool services, sqlbReadAndReleaseBuffers, probe:13
RETCODE : ZRC=0x86020001=-2046689279=SQLB_BADP "page is bad"
DIA8400C A bad page was encountered.
2008-09-22-11.46.45.910000+480 I806094H413 LEVEL: Error
PID : 1860 TID : 2732 PROC : db2syscs.exe
INSTANCE: DB2INST NODE : 000
FUNCTION: DB2 UDB, buffer pool services, sqlbReadAndReleaseBuffers, probe:13
DATA #1 : String, 126 bytes
Obj={pool:34;obj:6;type:0} State=x27 Page=140354 Cont=0 Offset=140352
BlkSize=12
sqlbReadAndReleaseBuffers error: num-pages=8
2008-09-22-11.46.45.942000+480 I806509H593 LEVEL: Error
PID : 1860 TID : 2732 PROC : db2syscs.exe
INSTANCE: DB2INST NODE : 000
MESSAGE : SQLB_OBJECT_DESC
DATA #1 : Hexdump, 68 bytes
0x04B6B5DC : 2200 0600 2200 0600 0000 0000 003A A2A6 "..."........:..
0x04B6B5EC : 40E5 0000 0000 0000 0000 0000 0000 0000 @...............
0x04B6B5FC : 0000 0000 0101 0000 2700 0000 0000 0000 ........'.......
0x04B6B60C : 0010 0000 2000 0000 0100 0000 2200 0600 .... ......."...
0x04B6B61C : 408C 7400 @.t.
SQL1034C The database is damaged.
2008-09-22-11.46.46.020000+480 I807104H356 LEVEL: Error
PID : 1860 TID : 2732 PROC : db2syscs.exe
INSTANCE: DB2INST NODE : 000
FUNCTION: DB2 UDB, buffer pool services, sqlbErrorHandler, probe:0
RETCODE : ZRC=0x86020001=-2046689279=SQLB_BADP "page is bad"
DIA8400C A bad page was encountered.
2008-09-22-11.46.46.020000+480 I807462H351 LEVEL: Error
PID : 1860 TID : 2732 PROC : db2syscs.exe
INSTANCE: DB2INST NODE : 000
FUNCTION: DB2 UDB, buffer pool services, sqlbErrorHandler, probe:0
DATA #1 : String, 75 bytes
Obj={pool:34;obj:6;type:0} State=x27
--注:Obj={pool:34;obj:6;type:0} State=x27,“pool”指的表空间ID,“obj”指的
对象ID
Prefetcher Error, in sqlbProcessRange
2008-09-22-11.46.46.020000+480 I807815H593 LEVEL: Error
PID : 1860 TID : 2732 PROC : db2syscs.exe
INSTANCE: DB2INST NODE : 000
MESSAGE : SQLB_OBJECT_DESC
DATA #1 : Hexdump, 68 bytes
0x04B6B5DC : 2200 0600 2200 0600 0000 0000 003A A2A6 "..."........:..
0x04B6B5EC : 40E5 0000 0000 0000 0000 0000 0000 0000 @...............
0x04B6B5FC : 0000 0000 0101 0000 2700 0000 0000 0000 ........'.......
0x04B6B60C : 0010 0000 2000 0000 0100 0000 2200 0600 .... ......."...
0x04B6B61C : 408C 7400 @.t.
可以从系统表中读取判断是哪个表受到损坏。例如:
select tabname from syscat.tables where tbspaceid=34 and tableid=6
数据库最严重的故障莫过于数据库损坏。从上面的例子来看,我们的数据库中有数据页受到损坏。出现SQL1034C错误时,我们首先执行操作系统命令。例如在AIX操作系统上,执行“errpt –d H –T PERM”命令来判断系统是否出现硬件损坏。然后尝试使用“db2 restart db sample”命令让数据库执行崩溃恢复。
如果上述办法不能解决问题,那么最好的办法是从备份恢复数据库。如果无法从备份恢复,那么可以根据损坏的原因尝试相应的解决方案。对于存储问题导致部分数据文件损坏,但是数据库还可以连接的情况,可以采用导出数据库的表结构和数据的方法来恢复数据库。当然对于损坏的表,导出是无法完成的。这时可以使用db2dart的导出数据功能来导出这些损坏的表的数据。如果数据库损坏到已经无法连接的程度,那么除了从备份恢复,唯一的办法就是使用db2dart来导出所有数据了。下面展示了使用db2dart命令时的提示信息:
运行命令 db2dart /DDEL
# Table object data formatting start.
# Please enter
# Table ID or name, tablespace ID, first page, num of pages:
# (suffic page number with 'p' for pool relative),
按照提示输入表名、表空间ID、起始页数、需要导出的页数。如果你的数据库非常大的话,这将是一个工作量非常大的事情。因此建议大家做好数据库备份。
9.1.5 inspect命令使用案例
inspect命令类似于db2dart命令,它同样可以用来检查数据库、表空间和表。 inspect命令和db2dart命令的主要区别是:inspect命令需要与数据库连接,并且可以在该数据库上同时有多个活动的数据库连接时执行;而db2dart命令在执行之前需要断开所有数据库连接,数据库上不能有活动的数据库连接。
inspect命令可以在有其他用户连接的情况下验证数据库的完整性。例如,使用“db2 inspect check database results keep <filename>”命令可以验证整个数据库的完整性,具体语法如下所示:
db2 " inspect check database results keep inspect.rel "
DB20000I INSPECT 命令成功完成。
在Windows平台下,输出文件在“C:\IBM\SQLLIB\实例名”或DB2INSTPORF变量指定的目录下;在Linux/UNIX平台下,输出文件在“$INSTHOME/sqllib/db2dump”目录下。输出的文件需要由db2instpf命令进行格式化,db2instpf命令的语法是:
db2inspf <data file> <out file>
例如:
db2inspf INSPECT.rel INSPECT.out
执行inspect命令时还可以加很多参数,使用时可以执行“db2 ? inspect”查看详细的命令选项。下面我们举几个inspect的使用案例:
例如,如果希望只检查表空间2中的数据,可执行以下命令:
db2 "inspect check tablespace tbspaceid 2 results keep inspect.rel"
DB20000I INSPECT 命令成功完成。
对数据库从表空间11对象2开始执行一致性检查,可执行以下命令:
db2 inspect check database begin TBSPACEID 11 OBJECTID 2 results checkts.out
产生的checkts.out报告的具体信息如下所示: