web-dev-qa-db-ja.com

「考えられるチェーンリンクの問題」の破損を修復する方法。

15 000 000レコードの大きなテーブルがあり、突然Select Topが機能しなくなりました。 MS SQL Management Studioを使用しています。

これは機能していません、クエリは0レコードを返します:

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

驚いたことに、1つのIDフィールドを選択しようとすると、それはパーセントで機能します。

正常に動作しています:

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

また、最後にby 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

ここで重要なことは2つあります。1)データベースをシングルユーザーモードに設定する必要があります。 2)データベースが稼働中で他の接続がある場合、SETユーザーコマンドは現在の接続を削除するためにROLLBACK IMMEDIATEを使用して取得する必要があります。

5
Tomas

データベースの破損に直面した場合、問題の範囲を特定する必要があります。破損したテーブル/インデックスは1つですか、それとも多数ですか?データベースでDBCC CHECKDBを実行することをお勧めします。

検索結果に応じて、次のオプションがあります(安全性の高い順に)。

  1. バックアップから復元する

    これは通常、最も簡単で安全なソリューションです。ただし、破損がどのくらい前に発生したかがわからない場合、これは実際的でない可能性があります。破損のない最新のバックアップがない可能性があります。また、データベースの使用状況によっては、1日分のデータを破棄して破損を修正すると、ビジネスを継続して実行できるという点で、非常にコストがかかる可能性があります。

    ただし、破損が深刻な場合は、これが唯一の解決策になる可能性があります。以下のオプションのいくつかを試しても、このオプションに戻る必要がある場合があります。

    バックアップがある場合は、それらを手元に置いておき、問題が解決するまで(可能な場合は)循環しないでください。

  2. 修復オプションを指定してDBCC CHECKTABLEまたはDBCC CHECKDBを使用します

    DBCC CHECKTABLEDBCC CHECKDB を実行した結果、正常な状態に復元するために使用できる修復オプションが表示された可能性があります。

    コマンドには同じ修復オプションがあります。

    • REPAIR_FAST-言われているように、いくつかの簡単なことを試しましたが、他の修復オプションよりも時間がかかりません。ご想像のとおり、これは成功する可能性が最も低いことも意味します。

    • REPAIR_REBUILD-これはREPAIR_FASTが行うことと同じですが、インデックスを最初から再構築しようとすることもできます。問題は非クラスタ化インデックスにあり、これで解決するはずです。

    • REPAIR_ALLOW_DATA_LOSS-示されているように、影響を受けるオブジェクトを使いやすいように復元しようとしますが、そのために部分的な行などを削除する必要がある場合があります。データの一部が失われる可能性があります。これが、バックアップの復元がしばしば最善の解決策である理由の1つです。

  3. (いわば)悪いテーブルのフランケンシュタイン

    このテーブルのみが影響を受ける場合、次のことを試みることができます。

    • テーブルが破損していないバックアップを探します(別の名前でバックアップを立ち上げます)。
    • 不良テーブルを削除します。
    • DBCC CHECKDBをもう一度実行して、問題が他の場所に移動していないことを確認します。そして
    • バックアップからテーブルとそのデータをコピーします。


    または、できるだけ多くの新しいデータを保持するようにするには:

    • 上記のように、バックアップの準備をします
    • テーブルでREPAIR_ALLOW_DATA_LOSSを使用します。
    • テーブルが機能している場合は、修復されたテーブルにないバックアップ内の行を探し、それらをコピーします。

コメントの CaM で示されているように、これを動機として使用して、データベースで定期的なメンテナンスタスクを実行していることを確認してください。

まず、今日でない場合は、定期的にバックアップを開始してください。私が管理するデータベースのほとんどは、毎週の完全バックアップと毎日の差分バックアップを持っているので、1日以上のデータを失うことはありません。

さらに、定期的にDBCC CHECKDBを実行して、修正が深刻になる前に破損を検出する必要があります。これも私が毎週実行しようとしているものです。

11
RDFozz