DB2數據庫壞頁

所謂數據庫損壞也就是說數據庫中的某些頁面被損壞了。對於DB2而言,頁面是操作系統分配的最小數據單元,它在主內存與任何其它輔助存儲(比如硬盤驅動器)之間傳輸。壞頁問題可能會對系統造成嚴重的性能衝擊。在某些情況下,它可能會導致頻繁的數據庫宕機。

一、壞頁的產生

數據庫壞頁可能在頁面的寫入、讀取、存儲、傳輸或處理過程中發生,這會向原始數據引入一些非計劃中的更改。數據庫壞頁問題的一些常見原因:

  1. 文件系統的損壞。

  2. 硬件故障。

  3. 內存損壞。

  4. DB2 BUG

  5. I/O和網絡問題。

  6. 不正確的應用程序編碼。

  7. 緩衝池      (sqldPage) 和文件系統中存儲的頁面的值不一致。

雖說損壞問題由各種原因而致,確切地查明是什麼導致了數據損壞是極具挑戰的。當 DB2檢測到一個頁面損壞時,它會停止所有處理,將數據庫關閉,阻止進一步的數據損害或丟失。

 

二、壞頁的類型

1.數據頁面損壞

2017-03-14-10.13.05.261082-360 I3442A358 LEVEL: Error PID : 393470 TID : 1 PROC : db2pfchr 0 INSTANCE: inst1 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. 2017-03-14-10.13.05.264301-360 I3801A437 LEVEL: Error PID : 393470 TID : 1 PROC : db2pfchr 0 INSTANCE: inst1 NODE : 000 FUNCTION: DB2 UDB, buffer pool services, sqlbReadAndReleaseBuffers, probe:13 DATA #1 : String, 158 bytes Obj={pool:9;obj:20;type:0} State=x27 Parent={9;20}, EM=1120, PP0=1152

 

如上錯誤消息所示,DB2 遇到了一個表空間 ID 爲 9、表 ID 爲 20 的壞頁。壞頁的對象類型被標記爲0,表明有數據頁面損壞。

可以通過查詢目錄表,確定哪個表有損壞的頁面:

db2 "select char(tabname,30),char(tabschema,30) from syscat.tables where tableid=20 and tbspaceid=9";

 

2.索引頁面損壞

2017-03-14-10.35.50.952434+000 I29308542A2532 LEVEL: Severe PID : 1175792 TID : 33926 PROC : db2sysc 0 INSTANCE: inst1 NODE : 000 DB : SAMPLE APPHDL : 0-7 APPID: *LOCAL.inst1.120130013528 AUTHID : TP0ADM EDUID : 33926 EDUNAME: db2redow (TP0) 0 FUNCTION: DB2 UDB, buffer pool services, sqlb_verify_page, probe:3 MESSAGE : ZRC=0x86020001=-2046689279=SQLB_BADP "page is bad" DIA8400C A bad page was encountered. DATA #1 : String, 64 bytes Error encountered trying to read a page - information follows : DATA #2 : String, 23 bytes Page verification error DATA #3 : Page ID, PD_TYPE_SQLB_PAGE_ID, 4 bytes 23046981 DATA #4 : Object descriptor, PD_TYPE_SQLB_OBJECT_DESC, 72 bytes Obj: {pool:9;obj:11076;type:1} Parent={8;11076}

如上錯誤消息所示,DB2 遇到了一個表空間中ID 爲9,索引ID 爲1322的壞頁。該索引所在表的表空間 ID 爲 8,表 ID 爲 1215。壞頁的對象類型被標記爲 1,表明有索引頁面損壞損壞。

可以通過查詢目錄表,確定哪個表的那個索引有損壞的頁面:

db2 "select char(a.tabname,30) tabname,char(a.tabschema,30) tabschema,b.indname from syscat.tables a,syscat.indexes b where a.tabname=b.tabname and a.tabschema=b.tabschema a.tableid=1215 and a.tbspaceid=8" and b.iid=1322;

 

3.CBIT損壞

CBIT是DB2使用的一種方法,用於確認從磁盤讀入緩衝池的一個頁面不是一個部分頁面,或者沒有從某種形式的損壞改變而來。

CBIT 背後的基本思想是,在寫入頁面之前將頁面上每個扇區(512 字節)的一個位數設置爲相同的值。在DB2將一個頁面刷新到磁盤上之前,計算校驗和並記錄在頁面上。在緩衝池中讀回一個頁面時,重新計算這一校驗和,並根據存儲的值對其進行檢查。如果有些位數不同,表明有一個部分頁面寫操作或磁盤損壞。

2017-03-14-10.45.17.559235-240 I1104A2616 LEVEL: Severe PID : 2551866 TID : 1 PROC : db2pfchr INSTANCE: inst1 NODE : 000 FUNCTION: DB2 UDB, buffer pool services, sqlbVerifyCBITS, probe:1110 MESSAGE : ZRC=0x86020019=-2046689255=SQLB_CSUM "Bad Page, Checksum Error" DIA8426C A invalid page checksum was found for page "". DATA #1 : String, 64 bytes Error encountered trying to read a page - information follows : DATA #2 : String, 95 bytes CBIT verification error bitExpected is 0, userByte is 33, sector 7 (from head of page, 0 based) DATA #3 : Page ID, PD_TYPE_SQLB_PAGE_ID, 4 bytes

注意,如果損壞不觸及存放CBIT的字節,在DB2以外對頁面做出的更改(文件系統故障、磁盤故障等)不會被注意到。CBIT 錯誤(校驗和錯誤)多半是因初始寫或讀期間的硬件或 OS 錯誤引起的。

 

4.事務日誌損壞

DB2中事務日誌只是對數據庫中發生的所有變更的一個記錄。要跟蹤事務做出的變更,需要一個方法來對數據變更和日誌記錄加時間戳。在DB2中,這一時間戳機制是使用一個日誌序列號 (LSN) 執行的。如果遇到一個損壞的日誌,可能會在db2diag.log中有如下類似的錯誤消息。

2017-03-14-11.37.21.143998+120 I8673583A553 LEVEL: Severe PID : 2498668 TID : 27358 PROC : db2sysc 56 INSTANCE: inst1 NODE : 056 DB : SAMPLE APPHDL : 998-22947 APPID: *N998.inst1.100607192315 AUTHID : LOADDSF EDUID : 27358 EDUNAME: db2agntp (SAMPLE) 56 FUNCTION: DB2 UDB, data protection services, sqlpgrlg, probe:291 DATA #1 : < reformatted > Error -2028994519 when reading LSN 00000B1C261B4FD3 from log file S0119292.LOG tellMe 1 dpsAcbFlags 1000 setSkipOutputBuf 0 2017-03-14-11.37.21.144202+120 I8674137A487 LEVEL: Severe PID : 2498668 TID : 27358 PROC : db2sysc 56 INSTANCE: inst1 NODE : 056 DB : SAMPLE APPHDL : 998-22947 APPID: *N998.inst1.100607192315 AUTHID : LOADDSF EDUID : 27358 EDUNAME: db2agntp (SAMPLE) 56 FUNCTION: DB2 UDB, data protection services, sqlpgrlg, probe:291 DATA #1 : < preformatted > HeadLsn 00000B1B8B996EB3, copyLookForLsn 00000B1C261B4FD3 2017-03-14-11.37.21.158065+120 I8675153A549 LEVEL: Error PID : 2498668 TID : 27358 PROC : db2sysc 56 INSTANCE: inst1 NODE : 056 DB : SAMPLE APPHDL : 998-22947 APPID: *N998.inst1.100607192315 AUTHID : LOADDSF EDUID : 27358 EDUNAME: db2agntp (SAMPLE) 56 FUNCTION: DB2 UDB, data protection services, sqlptudo, probe:1010 RETCODE : ZRC=0x87100029=-2028994519=SQLP_BADLSN "Invalid LSN value." DIA8538C An invalid log sequence number (LSN), the value was "".

如果日誌被損壞了,在數據庫前滾、崩潰恢復和 HADR 日誌回覆等需要回應日誌的情況下可能會引發嚴重的問題。數據庫前滾和崩潰恢復能夠維護數據庫中的一致性。它通過應用記錄在數據庫日誌文件中的事務來恢復數據庫。前滾是在還原數據庫或表空間備份映像之後調用的一個過程。HADR可以提高數據的安全性。

 

二、排查壞頁

1.db2dart

db2dart的默認行爲是要檢查整個數據庫。在這種情況下只有數據庫名稱必須提供。默認情況下,db2dart會創建一個名爲 databaseName.RPT 的報告文件。對於單分區數據庫環境,文件會被創建到了當前目錄中。對於多分區數據庫環境,則文件會被創建到了診斷目錄的一個子目錄中。子目錄名爲DARTnnnn,其中 nnnn 是分區號。

如果數據庫很大,且只對一個表空間感興趣,可以使用/TS選項。使用該選項時,必須在命令行上提供表空間 ID(通過指定/TSI參數)或者可以根據db2dart提示輸入該 ID。類似的,可以使用/T選項檢查一個表及其相關對象(LOB 和索引等)。使用該選項時,必須提供表名稱或對象 ID 以及表所在的表空間的ID。要確定一個表的對象 ID 和表空間 ID,可以查詢 SYSIBM.SYSTABLES 目錄表。

eg:db2dart <dbname>

 

2.inspect

inspect命令類似於db2dart命令。它允許檢查數據庫、表空間和表的架構完整性,方法就是檢查數據庫的頁面,看頁面是否一致。兩個命令之間的顯著區別在於,在運行db2dart之前需要停用數據庫,而inspect需要一個數據庫連接,且可在同時有多個活躍的數據庫連接時運行。

egdb2 "inspect check database results keep inspect.rel" ;

 

三、修復壞頁

根據之前的討論,可以通過db2dart和inspect工具識別損壞頁面。通過查看生成的報告文件,可以估計損壞範圍。根據數據損壞的數量和涉及到的複雜度,需要決定最好的恢復計劃。

1.從數據損壞中修復

a.如果有數據庫備份,還原數據庫並前滾到日誌的末尾。如果可行的話這是最簡潔的方法,如果數據庫很小時首選該方法。

b.還可以還原表空間並前滾到日誌的末尾。如果損壞是小範圍的,這可能是最好的方法。

c.如果沒有有效的備份映像以及重新創建表的任何方式,可以使用db2dart以及/ddel來挽救數據。在此之前,需要使用db2look查找表的DDL。

參考命令:

db2look -d <dbname> -e -z <schema_name> -t <table_name> -o <output_file_name>

db2dart $DBNAME /DDEL /RPT 根據提示輸入表信息。

 

2.從索引損壞中修復

如果在 db2diag.log 和/或 db2dart 報告中有索引損壞的跡象,可以使用db2dart將索引標記爲無效,並去除壞的索引然後重建索引。db2dart有一個可將索引標記爲無效且使其處於刪除暫掛狀態的選項。可以使用db2dart /MI將受損的索引標記爲無效。

參考命令:

db2dart <dbname> /MI /TSI 9 /OI 1322

 

3.從 CBIT 錯誤中修復

要修復 CBIT 損壞錯誤,通過至少在受損表上運行db2dart(最好對整個數據庫運行它)來檢查問題的嚴重程度。可以根據CBIT錯誤是在數據頁面上還是索引上來決定上述討論的方法。

 

4.從日誌損壞中修復

可以使用db2cklog檢查歸檔日誌文件的有效性,確定在數據庫或表空間的前滾恢復、崩潰恢復、HADR回放日誌的過程中是否可以使用日誌文件。

a.如果在前滾過程中由於壞的日誌而發生錯誤,可以做的第一件事就是檢查 DB2 在爲哪個日誌文件報告錯誤。db2flsn可用於返回包含日誌記錄的文件的名稱,該日誌記錄根據指定日誌序列號 (LSN) 識別。因此如果在db2diag.log中有'bad_lsn'消息,可以使用db2flsn查找相應的日誌文件。如果日誌損壞是因爲一個缺失的日誌文件或一個不正確的日誌鏈上的一個日誌文件,則可以查找正確的日誌文件。如果前滾操作由於一個損壞的日誌而失敗,則可以選擇時間點前滾。前滾操作的指定時間點必須等於或晚於最小恢復時間。最小恢復時間 (MRT) 是當一個數據庫一致時前滾過程中最早的時間點。如果不能將日誌至少前滾到 MRT,就需要聯繫 IBM 支持團隊獲取協助。

b.如果在崩潰恢復中因一個壞的日誌文件而出現問題,需要還原最新的備份或聯繫 IBM 支持團隊獲取協助。

c.如果在HADR備用數據庫上,在日誌回覆期間,備用服務器可能會因爲一個壞的日誌而崩潰。可以檢查備用服務器上的 db2diag.log,找到壞的日誌文件並嘗試從主服務器上傳送該日誌文件的一個良好備份。一旦有了一個好的日誌文件,就可以啓動 HADR:

  1. 在備用節點上對      HADR 運行 start:db2 start      hadr on db <dbname> as standby。

  2. 在主節點上對 HADR      運行 start:db2 start hadr on      db <dbname> as primary。

如果上述嘗試失敗了,可能需要使用來自主服務器上的全新備份重新配置 HADR,並在備用服務器上還原它。

 

四、表壞頁批量修復

1.a.txt

tablename tableid tabspaceid

 

2.dart script:

DBNAME=sample

SCHEMA=db2inst1

RPTDIR=/backup/dartdata

sed 's/,/ /g' a.txt|while read line

do

echo $line | awk -F"," '{

tablename=$1

tableid=$2

tabspaceid=$3

printf("%s,%s,0,999999\nY\n%s\n",tableid,tabspaceid,tablename)

}' >inputfile

if [ -s inputfile ]

then

db2dart $DBNAME /DDEL /RPT $RPTDIR /RPTN ${tablename}.DEL < inputfile

fi

done

 

3.import script:

DBNAME=sample

SCHEMA=db2inst1

RPTDIR=/backup/dartdata

db2 connect to $DBNAME

sed 's/,/ /g' a.txt|while read line

do

echo $line | awk -F"," '{

tablename=$1

tableid=$2

tabspaceid=$3

db2 "import from /backup/dartdata/${tablename}.DEL of del commitcount 100000 insert into ${SCHEMA}.${tablename}";

done

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章