Sql-Server

如何修復“可能的連鎖問題”的損壞。

  • July 11, 2018

我有 15 000 000 條記錄的大表,突然 Select Top 停止工作。我使用 MS SQL 管理工作室。

這不起作用,查詢返回 0 條記錄:

SELECT TOP (10) 
      [Id]
     ,[Result]
     ,[DateStamp]
     ,[ConversionTime]
     ,[Converter]
     ,[SourceFileFormat]
     ,[DestinationFileFormat]
     ,[Ip]
     ,[Source]
     ,[Error]
     ,[UserId]
     ,[TokenId]
     ,[ConversionCost]
 FROM [ca-v2].[dbo].[Log]

令我驚訝的是,如果我嘗試選擇一個 ID 欄位,它會按百分比工作。

工作正常:

SELECT TOP (10) 
      [Id]        
 FROM [ca-v2].[dbo].[Log]

此外,如果我在最後添加 order by,查詢也開始工作:

SELECT TOP (10) 
      [Id]
     ,[Result]
     ,[DateStamp]
     ,[ConversionTime]
     ,[Converter]
     ,[SourceFileFormat]
     ,[DestinationFileFormat]
     ,[Ip]
     ,[Source]
     ,[Error]
     ,[UserId]
     ,[TokenId]
     ,[ConversionCost]
 FROM [ca-v2].[dbo].[Log]
 Order By [DateStamp]

我在桌子上跑DBCC CHECKTABLE,收到以下錯誤:

錯誤:消息 8978,級別 16,狀態 1,第 1 行

表錯誤:對象 ID 1029578706,索引 ID 1,分區 ID 72057594043367424,分配單元 ID 72057594045071360(鍵入行內數據)。頁面 (1:5044) 缺少上一頁 (1:5042) 的引用。可能的連鎖問題。

我能做些什麼呢?

在@RDFozz 的幫助下,我能夠使用 sql 修復損壞的索引

ALTER DATABASE "db" SET SINGLE_USER WITH ROLLBACK IMMEDIATE

go

DBCC CheckTable ("log", REPAIR_REBUILD) 

go

ALTER DATABASE "db" SET MULTI_USER WITH ROLLBACK IMMEDIATE

這裡有兩件重要的事情:1)必須將數據庫設置為單使用者模式。2) 如果數據庫正在生產中並且有其他連接,則 SET 使用者命令必須使用 ROLLBACK IMMEDIATE 來刪除目前連接。

當面臨數據庫損壞時,您需要確定問題的嚴重程度。你有一個損壞的表/索引,還是很多?您可能希望DBCC CHECKDB在數據庫上執行。

根據您的發現,您有以下選擇(按安全性降序排列):

  1. 從備份恢復

這通常是最簡單和最安全的解決方案。但是,如果您不確定損壞出現多久之前,這可能是不切實際的 - 您可能沒有最近的備份而沒有損壞。而且,根據數據庫的使用情況,丟棄一天的數據來修復損壞可能會非常昂貴,因為這會影響您繼續運營您的業務。

但是,如果損壞嚴重,這可能是您唯一可用的解決方案。即使您嘗試了以下一些選項,您也可能需要回到這個選項。

如果您有備份,請將它們放在手邊,並且在解決問題之前不要循環使用(如果可能)。 2. 使用DBCC CHECKTABLEDBCC CHECKDB與修復選項一起使用

您的執行DBCC CHECKTABLE和/或DBCC CHECKDB可能已經表明您可以使用修復選項來嘗試恢復正常。

這些命令具有相同的修復選項:

  • REPAIR_FAST- 正如它所說,它嘗試了一些簡單的事情,並且比其他修復選項花費的時間更少。正如您可能猜到的那樣,這也意味著它最不可能成功。
  • REPAIR_REBUILD- 這做了什麼REPAIR_FAST,但也願意嘗試從頭開始重建索引 - 問題出在非聚集索引中,這應該可以解決它。
  • REPAIR_ALLOW_DATA_LOSS- 如前所述,它將嘗試將受影響的對象恢復為可用狀態,但可能必須消除部分行等才能這樣做;您可能會失去一些數據。這就是為什麼恢復備份通常是最佳解決方案的原因之一。
  1. 科學怪人你的壞桌子(可以這麼說)

如果只有這張表受到影響,您可以嘗試:

  • 找到表未損壞的備份(並以不同的名稱建立備份);
  • 丟棄壞表;
  • DBCC CHECKDB通過再次執行確認這沒有將您的問題轉移到其他地方;和
  • 從備份中復製表及其數據。

或者,嘗試保留盡可能多的新數據:

  • 準備好備份,如上所述
  • REPAIR_ALLOW_DATA_LOSS在桌子上使用。
  • 如果表現在正在工作,請在備份中找到不在已修復表中的行,然後將它們複製進去。

正如CaM在評論中所指出的,您應該以此為動力,以確保您對數據庫執行定期維護任務。

首先,如果您不是今天,請開始定期備份。我管理的大多數數據庫都有每週完整備份和每日差異備份,因此我們永遠不會失去超過一天的數據。

此外,您還應該DBCC CHECKDB定期執行,以便在損壞變得嚴重到無法修復之前發現它。這也是我嘗試每週執行的東西。

引用自:https://dba.stackexchange.com/questions/211754