SQL Server數(shù)據(jù)庫(kù)損壞檢測(cè)以及SQL Server數(shù)據(jù)庫(kù)修復(fù)的解決方法
在一個(gè)理想的世界中,不會(huì)存在任何數(shù)據(jù)庫(kù)的損壞,就像我們不會(huì)將一些嚴(yán)重意外情況列入我們生活中的日常一樣,而一旦這類(lèi)事情發(fā)生,一定會(huì)對(duì)我們的生活造成非常顯著的影響,在SQL Server中也同樣如此,或許幾年內(nèi)您沒(méi)有遇見(jiàn)過(guò)數(shù)據(jù)庫(kù)中出現(xiàn)這類(lèi)情況,而一旦遇見(jiàn)這類(lèi)情況,往往伴隨著數(shù)據(jù)的丟失,宕機(jī),嚴(yán)重甚至您本身的職業(yè)生涯也會(huì)受到影響。因此對(duì)于這類(lèi)情況,我們需要了解數(shù)據(jù)庫(kù)損壞方面的知識(shí),以便我們能夠事前準(zhǔn)備,事后能夠處理。本篇文章會(huì)對(duì)數(shù)據(jù)庫(kù)損壞的原因、現(xiàn)象、事前和事后的一些處理方法以及簡(jiǎn)單的修復(fù)方法進(jìn)行探討。
數(shù)據(jù)庫(kù)為什么會(huì)損壞?
在了解數(shù)據(jù)庫(kù)損壞之前,首先我們要了解SQL Server是如何將數(shù)據(jù)保存到數(shù)據(jù)文件(MDF、NDF等)。無(wú)論更新還是插入數(shù)據(jù),數(shù)據(jù)都需要首先在內(nèi)存中的Buffer Pool駐留,然后通過(guò)CheckPoint和Lazy Writer等過(guò)程將內(nèi)存中的數(shù)據(jù)持久化到磁盤(pán)。在這個(gè)過(guò)程中,數(shù)據(jù)臟頁(yè)由內(nèi)存寫(xiě)入持久化的IO子系統(tǒng),在此期間,按照IO子系統(tǒng)的不同,數(shù)據(jù)可能經(jīng)過(guò)這幾層:
Windows(寫(xiě)數(shù)據(jù)一定調(diào)用的是WINDOWS API)
Windows底層的中間層(殺毒軟件,磁盤(pán)加密系統(tǒng))
網(wǎng)卡、路由器、交換機(jī)、光釬、網(wǎng)線等(如果IO子系統(tǒng)不是直連的話)
SAN控制器(如果使用了SAN)
RAID控制器(IO子系統(tǒng)做了RAID)
磁盤(pán)或SSD等持久化存儲(chǔ)器
因此,數(shù)據(jù)頁(yè)被寫(xiě)入持久化存儲(chǔ)期間,可能經(jīng)過(guò)上述列表中的幾項(xiàng)。在經(jīng)歷上述過(guò)程中,硬件環(huán)境會(huì)受到很多方面的影響,比如說(shuō)電壓是否穩(wěn)定、斷電、溫度過(guò)高或過(guò)低、潮濕程度等,而軟件方面,由于軟件都是人寫(xiě)的,因此就可能存在BUG,這些都可能導(dǎo)致數(shù)據(jù)頁(yè)在傳輸過(guò)程中出現(xiàn)錯(cuò)誤。
此外,影響磁盤(pán)的因素也包括電壓是否穩(wěn)定、灰塵等因素,這些也有可能引起磁盤(pán)壞道或整體損壞。
上面提到的所有因素都可以被歸結(jié)為IO子系統(tǒng)。因此,造成數(shù)據(jù)損壞的情況絕大部分是由IO子系統(tǒng)引起的,還有非常非常小的概率內(nèi)存芯片也會(huì)導(dǎo)致數(shù)據(jù)頁(yè)損壞,但這部分情況微乎其微,因此不在本文的討論之列。
上面提到的這些導(dǎo)致數(shù)據(jù)損壞的原因都屬于天災(zāi),還有一些人禍。比如說(shuō)通過(guò)編輯器等手動(dòng)編輯數(shù)據(jù)文件、數(shù)據(jù)庫(kù)中還有需要Redo和Undo的事務(wù)時(shí)(也就是沒(méi)有Clean Shutdown)刪除了日志文件(通常會(huì)導(dǎo)致數(shù)據(jù)庫(kù)質(zhì)疑)。
發(fā)現(xiàn)數(shù)據(jù)庫(kù)損壞
在我們知道可能造成數(shù)據(jù)庫(kù)的損壞原因之后,接下來(lái)我們來(lái)看SQL Server是如何監(jiān)測(cè)數(shù)據(jù)庫(kù)頁(yè)損壞的。
在SQL Server的數(shù)據(jù)庫(kù)級(jí)別,可以設(shè)置頁(yè)保護(hù)類(lèi)型,一共有三個(gè)選項(xiàng):None,CheckSum,Torn_Page_Detection,如圖1所示:

圖1.頁(yè)保護(hù)的三種選項(xiàng)
關(guān)于這三種選項(xiàng),首先,請(qǐng)無(wú)視None,請(qǐng)不要在任何場(chǎng)景下選擇該選項(xiàng),該選項(xiàng)意味著SQL Server不對(duì)頁(yè)進(jìn)行保護(hù)。
其次是TORN_PAGE_DETECTION,在SQL Server中,數(shù)據(jù)的最小單位是頁(yè),每一頁(yè)是8K,但是對(duì)應(yīng)磁盤(pán)上往往是16個(gè)512字節(jié)的扇區(qū),如果一個(gè)頁(yè)在寫(xiě)入持久化存儲(chǔ)的過(guò)程中,只寫(xiě)了一半的頁(yè),這就是所謂的TORN_PAGE_DETECTION,SQL Server通過(guò)每個(gè)扇區(qū)提512字節(jié)中前2位作為元數(shù)據(jù),總共16個(gè)扇區(qū)32位4字節(jié)的元數(shù)據(jù)(頁(yè)頭中標(biāo)識(shí)為:m_tornBits),通過(guò)該元數(shù)據(jù)來(lái)檢測(cè)是否存在部分寫(xiě)的TORN_PAGE,但該類(lèi)型的頁(yè)驗(yàn)證無(wú)法檢測(cè)出頁(yè)中的寫(xiě)入錯(cuò)誤,因此在SQL Server 2005及以上版本,盡量選擇CheckSum。
在SQL Server 2005及以上版本,引入了CheckSum,CheckSum可以理解為校驗(yàn)和,當(dāng)數(shù)據(jù)頁(yè)被寫(xiě)入持久化存儲(chǔ)時(shí),會(huì)根據(jù)頁(yè)的值計(jì)算出一個(gè)4字節(jié)的CheckSum存于頁(yè)頭(頁(yè)頭中標(biāo)識(shí)同為:m_tornBits),和數(shù)據(jù)在同一頁(yè)中一起保存在數(shù)據(jù)庫(kù)中。當(dāng)數(shù)據(jù)從IO子系統(tǒng)被讀取到內(nèi)存中時(shí),SQL Server會(huì)根據(jù)頁(yè)內(nèi)的值再次計(jì)算CheckSum,用該重新計(jì)算的CheckSum和頁(yè)頭中存儲(chǔ)的CheckSum進(jìn)行比對(duì),如果比對(duì)失敗,則SQL Server就會(huì)認(rèn)為該頁(yè)被損壞。
由CheckSum的過(guò)程可以看出,只有在頁(yè)被寫(xiě)入SQL Server的過(guò)程中才會(huì)計(jì)算CheckSum,因此如果僅僅改變數(shù)據(jù)庫(kù)選項(xiàng)的話,則頁(yè)頭中的該元數(shù)據(jù)并不會(huì)隨之改變。
與IO相關(guān)的三種錯(cuò)誤
通過(guò)上述CheckSum的原理可以看出,SQL Server可以檢測(cè)出頁(yè)損壞,此時(shí),具體的表現(xiàn)形式可能為下述三種錯(cuò)誤的一種:
823錯(cuò)誤,也就是所謂的硬IO錯(cuò)誤,可以理解為SQL Server希望讀取頁(yè),而Windows告訴SQL Server,無(wú)法讀取到該頁(yè)。
824錯(cuò)誤,也就是所謂的軟IO錯(cuò)誤,可以理解為SQL Server已經(jīng)讀取到該頁(yè),但通過(guò)計(jì)算CheckSum等值發(fā)現(xiàn)不匹配,因此SQL Server認(rèn)為該頁(yè)已經(jīng)被損壞。
825錯(cuò)誤,也就是所謂Retry錯(cuò)誤。
其中, 上述823和824錯(cuò)誤都是錯(cuò)誤等級(jí)為24的嚴(yán)重錯(cuò)誤,因此會(huì)被記錄在Windows應(yīng)用程序日志和SQL Server的錯(cuò)誤日志中,而引起該錯(cuò)誤的頁(yè)會(huì)被記錄在msdb.dbo.suspect_pages中。SQL Server錯(cuò)誤日志中也會(huì)記錄到出錯(cuò)頁(yè)的編號(hào),如圖2所示。

圖2.824錯(cuò)誤在SQL Server錯(cuò)誤記錄中的描述
因此,如果我們存在完善的備份的話,我們可以通過(guò)備份進(jìn)行頁(yè)還原(在此再次強(qiáng)調(diào)一下對(duì)于DBA來(lái)說(shuō),有”備”無(wú)患),一個(gè)簡(jiǎn)單的頁(yè)還原代碼如代碼清單1所示。
USE [master]
RESTORE DATABASE [Corrupt_DB] PAGE='1:155'
FROM DISK = N'C:\xxx.bak'
WITH FILE = 1, NORECOVERY, NOUNLOAD, STATS = 5
代碼清單1.一個(gè)簡(jiǎn)單的頁(yè)還原代碼,從備份中還原文件ID1中的第155頁(yè)
記得我們前面說(shuō)的,在讀取頁(yè)計(jì)算校驗(yàn)和時(shí)出錯(cuò),這既可能是被寫(xiě)入持久化存儲(chǔ)的頁(yè)本身出錯(cuò),也可能是在頁(yè)被讀取的過(guò)程中出錯(cuò),此時(shí)SQL Server會(huì)嘗試從IO子系統(tǒng)中再次讀取該頁(yè),最多可能是4次嘗試,如果在4次嘗試過(guò)程中校驗(yàn)和通過(guò),則會(huì)是825錯(cuò)誤,否則是824錯(cuò)誤。這里要注意,與823和824錯(cuò)誤不同的是,825錯(cuò)誤是一個(gè)等級(jí)僅為10的信息。
因此,由于有固定的錯(cuò)誤編號(hào),因此可以在SQL Server Agent中對(duì)823和824設(shè)置警報(bào)。
備份CheckSum
上述頁(yè)CheckSum只有在頁(yè)被使用時(shí)才會(huì)被校驗(yàn)頁(yè)的正確性。在備份數(shù)據(jù)庫(kù)時(shí),可以指定CheckSum選項(xiàng)來(lái)使得備份讀取的頁(yè)也計(jì)算校驗(yàn)和,從而保證了被備份的數(shù)據(jù)庫(kù)是沒(méi)有損壞的。在圖3的備份選項(xiàng)我們可以注意到這兩條:

圖3.CheckSum和Continue_After_Error選項(xiàng)
如果啟用了CheckSum,當(dāng)備份過(guò)程中發(fā)現(xiàn)了頁(yè)校驗(yàn)和錯(cuò)誤時(shí),就會(huì)終止備份,而啟用了Continue_After_Error選項(xiàng)的話,在檢測(cè)到校驗(yàn)和錯(cuò)誤時(shí),仍然繼續(xù)從而使得備份成功。
備份如果啟用了CheckSum選項(xiàng),除去檢測(cè)每一頁(yè)的校驗(yàn)和之外,還會(huì)在備份完成后,對(duì)整個(gè)備份計(jì)算校驗(yàn)和并存儲(chǔ)于備份頭中。
此外,對(duì)于備份,我們還可以通過(guò)Restore Verifyonly with CheckSum來(lái)驗(yàn)證備份,來(lái)保證備份的數(shù)據(jù)沒(méi)有被損壞。
DBCC CheckDB
前面提到SQL Server發(fā)現(xiàn)錯(cuò)誤的方法有兩種,分別為在讀取頁(yè)時(shí)和在備份時(shí)(本質(zhì)上也是讀取頁(yè))。但如果我們希望對(duì)于數(shù)據(jù)一致性的檢查更加的激進(jìn),那我們應(yīng)該定期使用CheckDB來(lái)檢查數(shù)據(jù)的一致性,而不至于在生產(chǎn)時(shí)間數(shù)據(jù)被讀取時(shí)才能發(fā)現(xiàn)錯(cuò)誤。
CheckDB命令會(huì)對(duì)整個(gè)數(shù)據(jù)庫(kù)做所有的一致性檢查。當(dāng)檢查對(duì)象是Master數(shù)據(jù)庫(kù)時(shí),CheckDB還會(huì)檢查ResourceDB。
CheckDB最簡(jiǎn)單的用法如代碼清單2所示,在當(dāng)前數(shù)據(jù)庫(kù)上下文中直接執(zhí)行CheckDB,將會(huì)檢查當(dāng)前數(shù)據(jù)庫(kù)中所有的一切。
DBCC CHECKDB
代碼清單2.CheckDB最簡(jiǎn)單的用法
CheckDB命令在企業(yè)版中會(huì)使用多線程來(lái)進(jìn)行,會(huì)對(duì)整個(gè)數(shù)據(jù)庫(kù)進(jìn)行一致性檢查,在該過(guò)程中,使用了內(nèi)建數(shù)據(jù)庫(kù)快照的方式進(jìn)行,因此不會(huì)造成阻塞,但CheckDB會(huì)消耗大量的CPU、內(nèi)存和IO。因此CheckDB要選擇在維護(hù)窗口時(shí)間或是系統(tǒng)閑時(shí)進(jìn)行。
默認(rèn)情況下,CheckDB命令會(huì)將輸出所有的信息,但通常我們并不關(guān)心這些信息,而是只關(guān)心錯(cuò)誤信息,因此實(shí)際中通常給DBCC指定不顯式信息的參數(shù),如代碼清單3所示。
DBCC CHECKDB WITH NO_INFOMSGS;
代碼清單3.CheckDB通常搭配N(xiāo)o_InfoMsgs參數(shù)
實(shí)際上,CheckDB是一套命令的匯總,CheckDB會(huì)依次檢查下述內(nèi)容:
初次檢查系統(tǒng)表
分配單元檢查(DBCC CHECKALLOC)
完整檢查系統(tǒng)表
對(duì)所有表進(jìn)行一致性邏輯檢查(DBCC CHECKTABLE)
元數(shù)據(jù)檢查(DBCC CHECKCATALOG)
SSB檢查
索引視圖、XML索引等檢查
首先,當(dāng)發(fā)現(xiàn)系統(tǒng)表?yè)p壞時(shí),只能通過(guò)備份進(jìn)行恢復(fù)(這也是為什么備份除TempDB之外的系統(tǒng)表非常重要)。其次,在一個(gè)大數(shù)據(jù)庫(kù)中,做一次CheckDB時(shí)間會(huì)非常長(zhǎng),維護(hù)窗口時(shí)間或系統(tǒng)閑時(shí)的時(shí)間可能無(wú)法Cover這段時(shí)間,那么我們可以將CheckDB的任務(wù)分散到CHECKALLOC、DBCC CHECKTABLE、DBCC CHECKCATALOG這三個(gè)命令中。
更多關(guān)于CheckDB的詳細(xì)信息,請(qǐng)參閱:http://technet.microsoft.com/en-us/library/ms176064.aspx。
數(shù)據(jù)庫(kù)損壞的修復(fù)
數(shù)據(jù)庫(kù)損壞最行之有效的辦法就是存在冗余數(shù)據(jù),使用冗余數(shù)據(jù)進(jìn)行恢復(fù)。所謂的冗余數(shù)據(jù)包括熱備、冷備、和暖備。
使用鏡像或可用性組作為熱備,當(dāng)檢測(cè)到錯(cuò)誤時(shí),可以自動(dòng)進(jìn)行頁(yè)修復(fù)(鏡像要求2008以上,可用性組是2012的功能)。鏡像當(dāng)主體服務(wù)器遭遇824錯(cuò)誤時(shí),會(huì)向鏡像服務(wù)器發(fā)送請(qǐng)求,將損壞的頁(yè)由鏡像復(fù)制到主體解決該問(wèn)題。對(duì)于可用性組,如果數(shù)據(jù)頁(yè)是在主副本上發(fā)現(xiàn)的,則主副本將會(huì)向所有輔助副本發(fā)送廣播,并由第一個(gè)響應(yīng)的輔助副本的頁(yè)來(lái)修復(fù)頁(yè)錯(cuò)誤,如果錯(cuò)誤出現(xiàn)在只讀輔助副本,則會(huì)向主副本請(qǐng)求對(duì)應(yīng)的頁(yè)來(lái)修復(fù)錯(cuò)誤。在這里有一點(diǎn)值得注意的是,無(wú)論是哪一種高可用性技術(shù),都不會(huì)將頁(yè)錯(cuò)誤散播到冗余數(shù)據(jù)中,因?yàn)镾QL Server中所有的高可用性技術(shù)都是基于日志,而不是數(shù)據(jù)頁(yè)。
其次是使用暖備或冷備來(lái)還原頁(yè),我已經(jīng)在代碼清單1中給出了詳細(xì)的代碼,這里就不細(xì)說(shuō)了。
如果沒(méi)有合適的備份存在,如果損壞的數(shù)據(jù)頁(yè)是存在于非聚集索引上,那么你很幸運(yùn),只需要將索引禁用后重建即可。
如果存在基準(zhǔn)的完整備份,并且日志鏈沒(méi)有斷裂(包括差異備份可以Cover日志缺失的部分),則可以通過(guò)備份尾端日之后還原數(shù)據(jù)庫(kù)來(lái)進(jìn)行修復(fù)。
最后,如果基礎(chǔ)工作做的并不好,您可能就需要通過(guò)損失數(shù)據(jù)的方式來(lái)?yè)Q回?cái)?shù)據(jù)庫(kù)的一致性,我們可以通過(guò)DBCC CheckDB命令的REPAIR_ALLOW_DATA_LOSS來(lái)修復(fù)數(shù)據(jù)庫(kù)。使用該方法可能導(dǎo)致數(shù)據(jù)損失,也可能不會(huì)導(dǎo)致數(shù)據(jù)損失,但大部分情況都會(huì)通過(guò)刪除數(shù)據(jù)來(lái)修復(fù)一致性。使用REPAIR_ALLOW_DATA_LOSS需要將數(shù)據(jù)庫(kù)設(shè)置為單用戶(hù)模式,這意味著宕機(jī)時(shí)間。
無(wú)論是哪種情況修復(fù)數(shù)據(jù)庫(kù),都要考慮是否滿(mǎn)足SLA,如果出現(xiàn)了問(wèn)題之后,發(fā)現(xiàn)無(wú)論用哪種方式都無(wú)法滿(mǎn)足SLA的話,那只能檢討之前的準(zhǔn)備工作并祈禱你不會(huì)因此丟了工作。
小結(jié)
本篇文章闡述了數(shù)據(jù)庫(kù)損壞的概念、SQL Server檢測(cè)損壞的原理、CheckDB的原理及必要性和簡(jiǎn)單的修復(fù)手段。對(duì)于數(shù)據(jù)庫(kù)損壞事前要做好充足的準(zhǔn)備,在事后才不會(huì)后悔莫及。就像買(mǎi)保險(xiǎn)一樣,你可不會(huì)希望出了事以后再去買(mǎi)保險(xiǎn)吧?
相關(guān)文章
多種SQL Server數(shù)據(jù)庫(kù)備份方法的精細(xì)講述教程
SQL Server數(shù)據(jù)庫(kù)備份有兩種方式,一種是使用BACKUP DATABASE將數(shù)據(jù)庫(kù)文件備份出去,另外一種就是直接拷貝數(shù)據(jù)庫(kù)文件mdf和日志文件ldf的方式。下面將將為大家介紹一下后者2014-03-03SQL server數(shù)據(jù)庫(kù)查詢(xún)語(yǔ)句使用方法詳細(xì)講解
簡(jiǎn)單的Transact-SQL查詢(xún)只包括選擇列表、FROM子句和WHERE子句。它們分別說(shuō)明所查詢(xún)列、查詢(xún)的表或視圖、以及搜索條件等。今天小編為大家詳細(xì)講解SQL server數(shù)據(jù)庫(kù)查詢(xún)語(yǔ)句2014-03-03
輕松學(xué)編程--輕松學(xué)SQL Server數(shù)據(jù)庫(kù) (張欽、崔程、李立新等編著) pdf
本書(shū)由淺入深地講解了SQL Server 2008中的各種常用知識(shí)點(diǎn),其中包括:安裝SQLServer 2008,SQL Server2008管理工具集,數(shù)據(jù)庫(kù)和數(shù)據(jù)庫(kù)表的管理,T-SQL語(yǔ)言基礎(chǔ),使用T-SQL2013-11-19unity3d怎么連接sql server數(shù)據(jù)庫(kù)
雖然在Unity3D中能夠通過(guò)PlayerPrefs類(lèi)來(lái)保存和讀取數(shù)據(jù),但是一旦數(shù)據(jù)量增大,僅僅通過(guò)代碼的方式存取數(shù)據(jù),這樣的工作量是非常大的2013-11-18
SQL Server數(shù)據(jù)庫(kù)應(yīng)用與開(kāi)發(fā)網(wǎng)絡(luò)大講堂 PDF 掃描版[119M]
全面介紹SQL server數(shù)據(jù)庫(kù)應(yīng)用與開(kāi)發(fā)知識(shí)2013-05-08SQL SERVER數(shù)據(jù)庫(kù)清空日志圖文教程分享
這個(gè)工具一清就可以清干凈的。使您再也不用擔(dān)心數(shù)據(jù)庫(kù)日志文件超過(guò)幾百兆或上GB級(jí)而煩惱2012-11-19VS2008連接SQL Server數(shù)據(jù)庫(kù)文件出錯(cuò)的解決方法
用代碼直接連SQL Server服務(wù)器沒(méi)有問(wèn)題,但在項(xiàng)目中數(shù)據(jù)源改用SQL Server數(shù)據(jù)庫(kù)文件時(shí)出錯(cuò),提示錯(cuò)誤如下與SQL Server文件(*.mdf)的連接要求安裝SQL Server2005才能正常2012-10-28
北大青鳥(niǎo) ACCP5.0 S2 SQL Server數(shù)據(jù)庫(kù)設(shè)計(jì)和高級(jí)查詢(xún)(SQL Advance) 合
今天弄的最后一個(gè)最新北大青鳥(niǎo)課件(ppt文件)也就是最新的accp5.0,全套S2的課件。。。本人上傳的課件除了accp4.0不太全外,其他的S1,S2都是全的。。希望大家喜歡2012-10-22
SQLScripter 2.0.0.1 綠色版 SQL Server數(shù)據(jù)庫(kù)腳本
命令行工具,操作SQL Server 數(shù)據(jù)庫(kù)腳本 SQLs cripter 設(shè)計(jì)的架構(gòu)生成過(guò)程自動(dòng)化。 應(yīng)用程序腳本整個(gè)服務(wù)器。 安排自動(dòng)作業(yè)腳本的所有級(jí)別的數(shù)據(jù)庫(kù)對(duì)象和服務(wù)器級(jí)別對(duì)2011-10-24《SQL Server數(shù)據(jù)庫(kù)設(shè)計(jì)與管理》完整電子版PDF
這是一本2006年最新出版的一本全面講述SQLServer2000的基礎(chǔ)與應(yīng)用的書(shū)籍。曾作為國(guó)家重點(diǎn)院校的計(jì)算機(jī)專(zhuān)業(yè)教程。這本書(shū)實(shí)例豐富、淺顯易懂、圖文并茂,而且內(nèi)容詳2009-03-22





