在使用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報告的具體信息如下所示: