所謂數據庫損壞也就是說數據庫中的某些頁面被損壞了。對於DB2而言,頁面是操做系統分配的最小數據單元,它在主內存與任何其它輔助存儲(好比硬盤驅動器)之間傳輸。壞頁問題可能會對系統形成嚴重的性能衝擊。在某些狀況下,它可能會致使頻繁的數據庫宕機。sql
1、壞頁的產生數據庫
數據庫壞頁可能在頁面的寫入、讀取、存儲、傳輸或處理過程當中發生,這會向原始數據引入一些非計劃中的更改。數據庫壞頁問題的一些常見緣由:安全
文件系統的損壞。服務器
硬件故障。網絡
內存損壞。架構
DB2 BUG。ide
I/O和網絡問題。工具
不正確的應用程序編碼。性能
緩衝池 (sqldPage) 和文件系統中存儲的頁面的值不一致。編碼
雖然說損壞問題由各類緣由而致,確切地查明是什麼致使了數據損壞是極具挑戰的。當 DB2檢測到一個頁面損壞時,它會中止全部處理,將數據庫關閉,阻止進一步的數據損害或丟失。
2、壞頁的類型
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 爲 九、表 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能夠提升數據的安全性。
2、排查壞頁
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須要一個數據庫鏈接,且可在同時有多個活躍的數據庫鏈接時運行。
eg:db2 "inspect check database results keep inspect.rel" ;
3、修復壞頁
根據以前的討論,能夠經過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:
在備用節點上對 HADR 運行 start:db2 start hadr on db <dbname> as standby。
在主節點上對 HADR 運行 start:db2 start hadr on db <dbname> as primary。
若是上述嘗試失敗了,可能須要使用來自主服務器上的全新備份從新配置 HADR,並在備用服務器上還原它。
4、表壞頁批量修復
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