SQL Server 中的 DBCC 一致性錯誤
我在我們的生產 SQL Server 2014 中執行 DBCC CheckDB。它報告了一個一致性錯誤:
Failed:(-1073548784) Executing the query "DBCC CHECKDB(N'MYDB') WITH NO_INF..." failed with the following error: "Table error: Object ID 629577392, index ID 1, partition ID 72057594387039319, alloc unit ID 72057594045596759 (type LOB data). The off-row data node at page (1:6009), slot 24, text ID 15754068079 is not referenced. CHECKDB found 0 allocation errors and 1 consistency errors in table 'MYTABLE' (object ID 629577281). CHECKDB found 0 allocation errors and 1 consistency errors in database 'MYDB'. repair_allow_data_loss is the minimum repair level for the errors found by DBCC CHECKDB (MYDB).". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly.
由於我們沒有該數據庫的良好備份,我們必須路由到以下場景。
我做了什麼來解決問題:
- 我將最近的備份文件從 Prod 恢復到 UAT 並再次執行 DBCC CheckDB 以複製錯誤。同樣的一致性錯誤又回來了。
- Ran DBCC CHECKTABLE (MYTABLE) = 相同的一致性錯誤顯示:
Table error: Object ID 629577392, index ID 1, partition ID 72057594387039319, alloc unit ID 72057594045596759 (type LOB data). The off-row data node at page (1:6009), slot 24, text ID 15754068079 is not referenced. DBCC results for 'MYTABLE'. There are 53635 rows in 2705 pages for object "MYTABLE". CHECKTABLE found 0 allocation errors and 1 consistency errors in table 'MYTABLE' (object ID 629577281). repair_allow_data_loss is the minimum repair level for the errors found by DBCC CHECKTABLE
- 然後執行以下步驟:
– 步驟 1 更改數據庫
$$ MYDB $$SET SINGLE_USER WITH ROLLBACK IMMEDIATE; – 步驟 2 DBCC CHECKDB(N'
$$ MYDB $$’, REPAIR_ALLOW_DATA_LOSS);
Msg 8964, Level 16, State 1, Line 3 Table error: Object ID 629577392, index ID 1, partition ID 72057594387039319, alloc unit ID 72057594045596759 (type LOB data). The off-row data node at page (1:6009), slot 24, text ID 15754068079 is not referenced. The error has been repaired. There are 53635 rows in 2705 pages for object "MYTABLE".
– 步驟 3 DBCC CHECKDB ('
$$ MYDB $$’) —(重新執行以檢查任何其他錯誤 = 未報告錯誤) – 步驟 4 更改數據庫
$$ MYDB $$設置多使用者;—(將其設置回多使用者模式=使用者可以訪問數據庫) 我的問題/疑慮:
- 我怎麼知道哪些數據失去了?據我了解,似乎沒有任何數據失去,因為在修復之前該表有 53635 行。修復後它仍然有 53635 行。
- 將數據庫設置為單使用者模式時,我們是否需要為該確切站點安排停機時間/中斷?
- 在生產中進行修復後,需要注意哪些最佳實踐?
我怎麼知道哪些數據失去了?
那麼這真的很難找到 AFAIK,最好的方法是測試你的數據庫和應用程序功能。您說數據行相同,請同時檢查約束和業務規則。由於損壞僅限於一張表,並且您可以進行備份並進行恢復,我猜損壞並沒有那麼嚴重。在這種情況下,您可以在新恢復的數據庫上執行 checkdb repair,然後比較兩個數據庫中的表。好吧,這很難,但幾乎沒有其他方法。
將數據庫設置為單使用者模式時,我們是否需要為該確切站點安排停機時間/中斷?
是的,顧名思義,如果允許單個使用者,則需要啟動其他使用者,包括應用程序。數據庫的修復是離線操作,因此需要停機。
在生產中進行修復後,需要注意哪些最佳實踐?
在數據庫上再次執行 checkdb,如果它沒有指向任何錯誤,我猜你的修復是成功的。另請注意,Checkdb 無法修復某些問題。如果你想縮短這個因為數據庫很大,那麼你可以執行
dbcc checkconstraint()
. 完整的 checkdb 將包括 checkconstraint。另請閱讀緊急模式修復如何工作?
看起來它是來自行外 LOB 列(例如
varchar(max)
orvarbinary(max)
)的孤立數據,並且 DBCC 已將其刪除。沒有刪除整行。鑑於它沒有被任何行引用,或者該行以某種方式失去了引用,您必須確定哪一行缺少數據;或者它應該被設置為 null 並且數據最終成為孤立的。
如文件所述,要使用修復選項,數據庫必須處於單使用者模式。因此必須安排停機時間。
但是,您可以使用
DBCC CHECKTABLE WITH REPAIR_ALLOW_DATA_LOSS
. 這將最大限度地減少停機時間。**數據庫通常非常有彈性。**即使是意外關閉,通常也可以恢復到一致的狀態。
通常,數據庫不一致可能來自以下幾種情況之一:
- 物理磁碟故障。為此,最好的解決方案是鏡像驅動器。
- 作業系統問題,例如錯誤的驅動程序或防病毒軟體、實際的病毒/惡意軟體、其他作業系統錯誤。其中,有缺陷的司機最有可能。
- 記憶體故障。對於 ECC 伺服器 RAM,這不太可能發生。
- 在沒有斷電保護的驅動器上,意外斷電也可能導致它。確保您的驅動器具有 PLP。
定期調度
DBCC
對於監控損壞發生是必不可少的,伺服器不一定會自動注意到它。此外,**良好的備份計劃是避免需要搞亂維修的最佳方式。**每晚進行一次完整備份,再加上每 10 或 15 分鐘一次的事務日誌備份,可以最大限度地減少數據失去。