SQL Server,我無法修復的一致性錯誤
使用者數據庫上的 DBCC CHECKDB 返回此錯誤
Msg 8992, Level 16, State 1, Line 1 Check Catalog Msg 3851, State 1: An invalid row (class=128,depid=65536,depsubid=0) was found in the system table sys.syssingleobjrefs (class=128).
此錯誤在使用者數據庫中,而不是在
master
!當人們嘗試檢查主數據庫並在不同的伺服器上恢復時,Internet 上到處都是專門針對此錯誤的文章。事實並非如此。我嘗試了所有常用的魔法,但沒有成功。
DBCC CHECKDB WITH ALL_ERRORMSGS, NO_INFOMSGS --error ALTER DATABASE DBCopy SET SINGLE_USER WITH ROLLBACK IMMEDIATE DBCC CHECKDB (DBCopy, REPAIR_ALLOW_DATA_LOSS) --output reports the same error DBCC CHECKDB WITH ALL_ERRORMSGS, NO_INFOMSGS --error --no hope but just in case ALTER DATABASE DBCopy SET EMERGENCY DBCC CHECKDB (DBCopy, REPAIR_ALLOW_DATA_LOSS) --the same error reported DBCC CHECKDB WITH ALL_ERRORMSGS, NO_INFOMSGS --error ALTER DATABASE DBCopy SET MULTI_USER
我們沒有沒有此錯誤的備份。這個錯誤看起來完全無害。數據庫和應用程序工作得很好。
微軟 SQL Server 2019 (RTM-CU14)
數據庫已啟用記憶體。
在我開始重建數據庫之前有什麼要嘗試的嗎?
PS我重建數據庫。
看來您有一行
sys.syssingleobjrefs
與其他系統表中的行不對應。
sys.syssingleobjrefs
被列為System Base Table,並且只能通過 DAC(管理員)連接訪問。您可以使用sqlcmd.exe -A
.文件說:
若要綁定到系統基表,使用者必須使用專用管理員連接 (DAC) 連接到 SQL Server 實例。嘗試從系統基表執行 SELECT 查詢而不使用 DAC 進行連接會引發錯誤。
重要的
使用 DAC 訪問系統基表僅適用於 Microsoft 人員,它不是受支持的客戶方案。
只有在沒有其他選擇的情況下,我才會建議這樣做。亂用系統表會破壞您的數據庫。
因此,您以管理員身份登錄或以
sa
. 您可能只想刪除無效行,希望這可以解決問題。警告!:
這樣做完全由您自擔風險。我強烈建議您備份數據庫,將其還原到完全不同的實例,然後先在那裡進行測試。
USE [DBCopy]; GO ALTER DATABASE DBCopy SET SINGLE_USER WITH ROLLBACK IMMEDIATE; GO DELETE FROM sys.syssingleobjrefs WHERE class = 128 AND depid = 65536 AND depsubid = 0; GO DBCC CHECKDB (DBCopy, REPAIR_ALLOW_DATA_LOSS) WITH NO_INFOMSGS, TABLOCK; GO
修復或刪除損壞的行將不起作用,因為此系統表不可通過經典 T-SQL 寫入。
根據該使用者數據庫的大小,可以轉儲/恢復數據庫以重建系統目錄,從而消除對象和目錄之間的不同步。
我建議您不要備份/恢復而是轉儲/恢復,因為備份/恢復將保持對象和目錄之間的不同步。
首先,確保數據庫上方的應用程序已關閉,或者至少與數據庫的連接池已關閉。
您可以首先將數據庫設置為單使用者模式(如果未關閉,這將意味著應用程序停機)。
ALTER DATABASE DBCopy SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
然後通過 SSMS 使用右鍵點擊相關數據庫並選擇“任務 > 生成腳本…”
在以下嚮導中,選擇要導出的對象(系統表引用的對象)。
導出完成後,刪除系統表引用的對象並通過執行導出的腳本恢復它們。
然後將數據庫返回到 MULTI_USER :
ALTER DATABASE DBCopy SET MULTI_USER;
我建議您首先通過預生產或基準環境嘗試該過程。這樣,您將能夠在完全不影響生產的情況下測試解決方案。
PS:要找出您的系統表涉及哪個對象,您將不得不探勘 syssingleobjrefs 系統表(正如@Charlieface 所說,
sqlcmd -A
哪個是通過 DAC 的管理員訪問權限)。如果您沒有在伺服器上安裝 sqlcmd,您可能必須啟用“遠端 DAC”才能通過網路使用管理員訪問權限。
PS (2) :最棘手的部分可能是找出哪個對象與您的損壞數據相關,因為這些是系統表和未記錄的表,很難告訴您該引用背後依賴於哪個對象。
PS(3):如果您無法將手指放在該系統表引用的對像上。最後一個選項是轉儲/恢復表的所有對象(這當然會涉及更長的停機時間)。