[SQL][心得報告]「Corrupt Your Database - On Purpose!」影片之課前預習

[SQL][心得報告]「Corrupt Your Database - On Purpose!」影片之課前預習

這幾天看了朋友所介紹的一個短片,介紹如何修復已經損毀的資料庫,感覺內容非常的詳細,想要推薦給內部的工程人員。但是擔心大家看的時候對一些指令和觀念不熟悉,因此我先對這個短片上所提到的一些東西,做個前情哉要,方便大家觀看。

 

1. SQL Server 真的那麼容易損毀嗎 ? 正常來說在硬體設備正常狀況下,應該很不容易發生這樣的問題。因為關聯式資料庫要符合交易的 ACID 特定 ( Atomicity、Consistency、Isolation 和 Durability ),特別在 Durability (耐久性) 的特性上,透過交易紀錄檔的處理,正常狀況下資料是不會遺失。但此次所要介紹的主要是針對當實體檔案有發生異常的時候,來針對異常狀況做處理。

2. Page Verify : SQL Server 在 2005 前,在資料庫選項中上的頁面確認 ( Page Verify ) 上雖然可以使用 Torn Page Detection 的時候,但他只是透過將 Page 分成 16 的小塊,每塊前面有個識別碼,這樣每次寫入的時候應該所有小塊都會有相同的識別碼,因此用來偵測是否有寫入不完整的狀況。但從 SQL Server 2005 版開始,增加了一個 CHECKSUM 的設定值,在每頁上都會紀錄 CHECKSUM 的值在 Page Header,因此當 Page 中有資料在寫入後被變更,或者是讀取有異常的時候,SQL Server 就會發生錯誤訊息,讓我們可以來做後續的處理動作。
 

3. DBCC CHECKDB : 這是一組用來檢查和修復資料庫的指令。在這裡我們雖然有提到可以用這組指令來修復。而當你要使用修復功能的時候,他會有兩組修復參數可以來使用,分別是 REPAIR_ALLOW_DATA_LOSS  和 REPAIR_REBUILD

前者 ( REPAIR_ALLOW_DATA_LOSS )顧名思義,就是有可能會導致資料遺失,因此在影片中不是採用這樣的方式,而是從資料庫備份和交易紀錄備份中取回來異常 Page 的資料,來達到不損失任何資料的最佳方式。一般我們會這樣做,通常是沒有備份檔的情況,或者是有備份,但是距離時間太久,不想損失這中間的資料,但最重要的是,就算能修復,也不能保證資料是正確的。

後者 ( REPAIR_REBUILD ) 通常都不是發生在資料頁上,因此這個時候 SQL Server 如果可以修復,那麼在不會有資料遺失的狀況下,SQL Server 會採用可修復的方式將異常頁面做處理。

除此之外,在影片中還會使用到另外一個檢查時所使用的參數 NO_INFOMSGS,這個參數主要是減少一般提示資訊的產生,因為當資料庫內有多個資料表的時候,當執行 DBCC CHECKDB 他會將檢查的經過都輸出,而使用 NO_INFOMSGS 的時候,表示我們只關注有異常的訊息,這樣可以方便我們查看。

4. 查看 Page 資料,目前我們可以採用兩種方式來做處理。第一種是早期的作法,當時因為沒有相關的 DMV ( Dynamic Management View ),我們會透過幾個 undocumented 的指令 DBCC INDDBCC PAGE的指令。會先利用 DBCC IND,可以先查看某個資料庫的特定物件,目前使用那些 PAGE。接著再透過 DBCC PAGE 的指令,來細看每個 PAGE 的內容。

 

而在影片中是採用 SQL Server 2012 開始所提供的 sys.dm_db_database_page_allocations 這個 DMV,此部分的細節可以參考之前的另外一篇文章 ( [SQL][問題處理]資料表在每個資料檔案各占用多少空間

5. Recovery Mode : 在影片中因為要做頁面還原 ( Page Restore ),所以必須要把資料庫復原模式設定為完整 ( Full ),這樣才可以進行交易紀錄備份。因此當資料庫發生問題的時候,就要找最近一次完整備份的檔案,和交易紀錄檔一起搭配,並且在還原資料庫的時候要去指定要還原的頁面。但如果一開始資料庫復原模式是簡單 ( Simple ),那就不能這樣來進行了。

 

6. OFFLINE : 在展示過程中,作者會把資料庫先做OFFLINE ( 離線 ),然後再進行資料庫檔案修改,之所以要這樣做的原因是當資料庫服務一起動的時候,這些資料庫檔案會被 SQL Server 給獨佔,因此必須要先 Detach ( 卸離 )或者是離線後才可以進行修改實體檔案內容。但如果使用卸離的話,雖然看起來是一樣,但有可能會造成你在掛載的時候因為檔案異常,造成 SQL Server 無法掛載,也就沒有辦法來進行處理了。因此當我們在進行資料庫維護的時候,不要一有異常就把資料庫給卸離,應該先想辦法在 SQL Server 還可以去連線的時候去處理,否則當你真的卸離有問題的資料庫後,後續要把資料庫掛載回來還要花費不少的功夫。

 

7. INDEX ID : SQL Server 的索引識別碼是從 0 ~ 250 的數值,其中 0 代表是 HEAP ( 堆積 )、1 代表 Clustered index ( 叢集索引 ),大於 1 以上表示 Nonclustered index ( 非叢集索引 ),因為從 SQL Server 2008 開始,預設 Primary Key 就是 Cluster Index,因此影片中會提到當 Index Id 是 1 的時候,必須要用還原來做修復,因為有異常的是 DATA PAGE。只是這個如果要挑剔的話,應該是要說當你的索引識別碼是 HEAP & Cluster Index 時,都要用還原來做修復。

 

8. ERROR LOG : SQL Server 預設的 錯誤記錄檔預設是有六個,但為什麼作者開啟異動記錄檔的時候會超過那個數量呢 ? 這個你可以透過 SSMS 在管理錯誤記錄檔,按下滑鼠右鍵選擇設定,就可以調整你想要的數量了。此次發生異常的錯誤代碼是 824,一般我們較常看到的讀取錯誤有 823824,前者通常都是硬體異常造成無法讀取的錯誤,後者是可以讀取但內容有錯。雖然這兩者處理方式相同,但如果發生 823 的時候,可能要更去了解一下設備是否需要淘汰更新了,畢竟是資料庫在使用的磁碟,這種異常很有可能造成很大的災難。

 

9. Disaster Recovery : 之前在課堂上,有些學生會問當發生異常的時候,為什麼要先做 Backup database,而有一些書籍和文章,卻是直接 Restore Database,到底哪個才是對的呢 ? 其實這兩個方式都是對的,前者是指當發生異常時,SQL Server 還是啟動著的狀況下,我們還可以連到 SQL Server 上把資料庫最後的交易紀錄給備份出來,就如同影片中的作者的方式,利用 BACKUP LOG <database>  WITH NORECOVERY。 把最後的交易紀錄給備份資料,這樣才可以避免資料遺失。但倘落發生異常的時候 SQL Server 已經無法連線,或者是資料庫已經嚴重損毀,因此無法進行結尾紀錄備份的情況下,那麼有可能在最後一次進行交易紀錄備份後的資料,就有可能會遺失了。

 

10. Index Rebuild : 影片最後有介紹到當 Noncluster Index 發生異常的時候,因為並不是本身資料表上的資料頁發生異常,但因為 SQL Server 載入該索引時就導致異常,因此也無法直接使用 ALTER INDEX REBUILD 的方式來進行,以往我們遇到這種狀況,通常就是把索引刪除,然後再重建一個新的索引。影片中作者介紹一個更方便的方式,利用把 INDEX DISABLE 的方式,這樣當你使用指令去 Rebuild Index 的時候,SQL Server 就會按照 Index 原本的定義去重新建立一個新的索引,比我們之前用的方式方便多了。因為這樣你就不會遺漏索引上原本的相關設定,也不用去查原本索引建立的時候是放入那些欄位,實在是個聰明的方式。


影片內容 :