時(shí)間:2015-06-28 00:00:00 來源:IT貓撲網(wǎng) 作者:網(wǎng)管聯(lián)盟 我要評(píng)論(1)
在管理數(shù)據(jù)庫(kù)時(shí)很容易出現(xiàn)問題,但是出現(xiàn)數(shù)據(jù)庫(kù)頁(yè)損壞或校驗(yàn)錯(cuò)誤時(shí)該如何解決,這也是大家需要了解的重要內(nèi)容。
最近一直在進(jìn)一步學(xué)習(xí)數(shù)據(jù)庫(kù)故障的處理方面的知識(shí),做為一個(gè)數(shù)據(jù)庫(kù)維護(hù)人員,我即期望遇到所有的數(shù)據(jù)庫(kù)出錯(cuò)的案例,以增加自己的經(jīng)驗(yàn),但同時(shí)又擔(dān)心遇到這樣或那樣無法處理的數(shù)據(jù)庫(kù)故障而導(dǎo)致數(shù)據(jù)丟失。
前幾天看到一個(gè)文章,是說一個(gè)網(wǎng)站管理員在招聘DBA時(shí),提出一個(gè)問題:"如果在SQL Server 日志里發(fā)現(xiàn)一個(gè)頁(yè)損壞或是校驗(yàn)和錯(cuò)誤應(yīng)該如何處理?"網(wǎng)站管理員描述,大概有90%的應(yīng)聘者都會(huì)采用一個(gè)方案,用DBCC CHECKDB加上其中的一個(gè)修復(fù)選項(xiàng),但其中也基本沒有人能具體解釋DBCC CHECKDB修復(fù)的過程或是工作原理及能修復(fù)到什么程度。
借助聯(lián)機(jī)文檔以及個(gè)人的一些理解和經(jīng)歷,解釋一下如何面對(duì)這個(gè)問題:"當(dāng)數(shù)據(jù)庫(kù)頁(yè)損壞或校驗(yàn)和出錯(cuò)時(shí)如何處理?"
首先,需要先了解DBCC CHECKDB,聯(lián)機(jī)文檔url:
http://technet.microsoft.com/zh-cn/library/ms176064.aspx
通過聯(lián)機(jī)文檔,可以得知有REPAIR_ALLOW_DATA_LOSS | REPAIR_FAST | REPAIR_REBUILD三個(gè)修復(fù)選項(xiàng),而提供實(shí)際功能的只有REPAIR_ALLOW_DATA_LOSS和REPAIR_REBUILD兩個(gè),其 中REPAIR_ALLOW_DATA_LOSS 嘗試修復(fù)報(bào)告的所有錯(cuò)誤,這些修復(fù)可能會(huì)導(dǎo)致一些數(shù)據(jù)丟失;而且REPAIR_REBUILD執(zhí)行不會(huì)丟失數(shù)據(jù)的修復(fù),包括快速修復(fù)(如修復(fù)非聚集索引中 缺少的行)以及更耗時(shí)的修復(fù)(如重新生成索引);可見REPAIR_REBUILD是我們期望的。
當(dāng)你從SQL Server log里或是在程序查詢數(shù)據(jù)庫(kù)或是定期通過DBCC CHECKDB為數(shù)據(jù)庫(kù)做體檢的時(shí)候,出現(xiàn)了頁(yè)損壞或校驗(yàn)和出錯(cuò)信息時(shí),如:
---------------------------------------------------------------------------------------------------------------------------------? M8928sg , Level 16, State 1, Line 1? Object ID 2088535921, index ID 0, partition ID 72345201021503994, alloc unit ID 72345201051571606 (type In-row data): Page (1:94299) could not be processed.See other errors for details.? Msg 8939, Level 16, State 98, Line 1? Table error: Object ID 2088535921, index ID 0, partition ID 72345201021503994, alloc unit ID 72345201051571606 (type In-row data), page (1:94299). Test (IS_OFF (BUF_IOERR, pBUF->bstat)) failed.? CHECKDB found 0 allocation errors and 2 consistency errors in table 'yourtable' (object ID 2088535921).? CHECKDB found 0 allocation errors and 2 consistency errors in database 'yourdb'.? repair_allow_data_loss is the minimum repair level for the errors found by DBCC CHECKDB (yourdb).? --------------------------------------------------------------------------------------------------------------------------------- 現(xiàn)在我們應(yīng)該如何做?
? 1.通過上面的提示,告訴我們:對(duì)象 2088535921出錯(cuò),它是一個(gè)表,頁(yè)面為1:94299
? 2.接下來,我們判斷損壞的頁(yè)在堆上還是聚集索引還是非聚集索引,sql server方法為:
dbcc traceon (3604, -1)? go? dbcc page('yourdb', 1, 94299, 3)? go 在輸出的結(jié)果里(會(huì)報(bào)錯(cuò),但可以看到頁(yè)頭信息),可以看到
Metadata: IndexId = n
如果n是0而表示是堆,1表示是聚集索引,>1是表示非聚集索引
ps:其實(shí)從提示信息的Object ID 2088535921, index ID 0 ,也可以簡(jiǎn)單判斷是堆.
? 3.根據(jù)上面的第2步,我們知道這個(gè)頁(yè)面是堆,這對(duì)我們來講,不是好消息,因?yàn)槿绻?1,我們可以刪除該非聚集索引,再重建索引,不會(huì)丟失數(shù)據(jù),而0或1則是元數(shù)據(jù)受損,這意味著有丟失元數(shù)據(jù)的可能性。
那么如何僅僅修復(fù)這個(gè)數(shù)據(jù)頁(yè)呢,這里我們假設(shè)該庫(kù)是full模式,并且有良好的備份策略,有全備和日志備份。
那么我們可以進(jìn)行頁(yè)面級(jí)還原操作,步驟如下:
a.首先進(jìn)行一次日志備份,如果你不放心,還可以再做一個(gè)全備;
backup log yourdb to disk='D:\DBBak\yourdb_a.trn'
b.通過完整備份來恢復(fù)該page. (yourdb.bak是一個(gè)全備。);
restore database yourdb page= '1:94299' from disk='D:\DBBak\yourdb.bak' with norecovery
c.恢復(fù)這個(gè)全備之后的差異(假設(shè)有差異yourdb.dif),如果沒有差異備,直接到d步驟;
restore database yourdb from disk='d:\DBBak\yourdb.dif'with norecovery
d.恢復(fù)之后的log備份,可能有多個(gè)(假設(shè)為yourdb_1.trn,yourdb_2.trn);
restore log yourdb from disk='d:\DBBak\yourdb_1.trn' with norecovery? restore log yourdb from disk='d:\DBBak\yourdb_2.trn' with norecovery? restore log yourdb from disk='d:\DBBak\yourdb_a.trn' with norecovery e.做一個(gè)最新的日志備;
backup log yourdb to disk='D:\DBBak\yourdb_e.trn' f.還原最后的(e步驟)日志備份;
restore log yourdb from disk='d:\DBBak\yourdb_e.trn' with recovery g.結(jié)束
? 4.經(jīng)過步驟三之后,我們?cè)賮頇z查一下該表是否還有錯(cuò),從提示信息Object ID 2088535921里,我們查出表名tbname;
tbname: select object_name(2088535921) 然后 dbcc checktable('yourtable')檢測(cè),如果沒有報(bào)錯(cuò),則表示修復(fù)完成
? 5.最后,對(duì)整個(gè)庫(kù)再做一次dbcc checkdb檢查;
ps:需要注意的是,sql server 的page級(jí)恢復(fù)在企業(yè)版和開發(fā)版中,支持聯(lián)機(jī)恢復(fù)page數(shù)據(jù),在標(biāo)準(zhǔn)版只能脫機(jī)修復(fù);
在dbcc checkdb修復(fù)選項(xiàng)里,用repair_rebuild修復(fù)數(shù)據(jù),聯(lián)機(jī)文檔稱是不丟失數(shù)據(jù),但在某些環(huán)境下可能也會(huì)丟失數(shù)據(jù),不過,我沒遇到過:)
用repair_allow_data_loss選項(xiàng)時(shí),聯(lián)機(jī)文檔稱可能會(huì)丟失數(shù)據(jù),而對(duì)于堆或聚集索引的頁(yè)損壞,sql server 會(huì)釋放該頁(yè)面,造成數(shù)據(jù)的丟失,但repair_allow_data_loss選項(xiàng)有兩種情況是不會(huì)丟失數(shù)據(jù),一種是非聚集索引上的頁(yè)錯(cuò)誤,另外是lob頁(yè)數(shù)據(jù)錯(cuò)誤。
數(shù)據(jù)庫(kù)頁(yè)損壞總結(jié):
一定要有良好的數(shù)據(jù)庫(kù)備份策略,備份重于一切;
要有異機(jī)備份,并且時(shí)時(shí)同步該備份文件;
當(dāng)數(shù)據(jù)庫(kù)出現(xiàn)故障時(shí),不要過于心急,冷靜分析一下錯(cuò)誤;
如果不能確定如何做,可以借助google,如果你的錯(cuò)誤信息里中文的,請(qǐng)翻譯成英文后再google,這樣搜到解決方案的可能性更大;
做修復(fù)時(shí),一定要再備一次數(shù)據(jù)庫(kù);
dbcc checkdb的repair_allow_data_loss選項(xiàng)永遠(yuǎn)是最后的選擇。
結(jié)束,如有錯(cuò)誤,請(qǐng)指正。
關(guān)鍵詞標(biāo)簽:數(shù)據(jù)庫(kù)
相關(guān)閱讀
熱門文章 淺談JSP JDBC來連接SQL Server 2005的方法 SqlServer2005對(duì)現(xiàn)有數(shù)據(jù)進(jìn)行分區(qū)具體步驟 sql server系統(tǒng)表?yè)p壞的解決方法 MS-SQL2005服務(wù)器登錄名、角色、數(shù)據(jù)庫(kù)用戶、角色、架構(gòu)的關(guān)系
人氣排行 配置和注冊(cè)O(shè)DBC數(shù)據(jù)源-odbc數(shù)據(jù)源配置教程 如何遠(yuǎn)程備份(還原)SQL2000數(shù)據(jù)庫(kù) SQL2000數(shù)據(jù)庫(kù)遠(yuǎn)程導(dǎo)入(導(dǎo)出)數(shù)據(jù) SQL2000和SQL2005數(shù)據(jù)庫(kù)服務(wù)端口查看或修改 修改Sql Server唯一約束教程 SQL Server 2005降級(jí)到2000的正確操作步驟 sql server系統(tǒng)表?yè)p壞的解決方法 淺談JSP JDBC來連接SQL Server 2005的方法