データベース内の矛盾するページを修復する


8

SQL 2000 DBがあります。RAIDアレイの障害によりサーバーがクラッシュしました。DBCC CHECKDBを実行すると、9ページに27の一貫性エラーがあるというエラーが発生します。

これらのページでDBCC PAGEを実行すると、次のようになります。

Msg 8939, Level 16, State 106, Line 1
Table error: Object ID 1397580017, index ID 2, page (1:8404521). Test (m_freeCnt == freeCnt) failed. Values are 2 and 19.
Msg 8939, Level 16, State 108, Line 1
Table error: Object ID 1397580017, index ID 2, page (1:8404521). Test (emptySlotCnt == 0) failed. Values are 1 and 0.

示されたインデックスはクラスター化されておらず、2つの列を含む一意のconstarintによって作成されているため、インデックスを削除して再作成してみました。これにより、次のエラーが発生しました。

CREATE UNIQUE INDEX terminated because a duplicate key was found for index ID 2. Most significant primary key is '3280'. 
The statement has been terminated. 

しかし実行している

Select var_id,result_on
from tests
group by var_id,result_on
having count(*)>1

0行を返します。

これが私たちが計画していることです:

  • サーバーのクラッシュ前のDBのコピーを復元し、DBCC CHECKDBを実行する
  • それがきれいに戻った場合は、回復せずにもう一度復元します
  • 後続のすべてのTLOGバックアップを適用する
  • 本番アプリを停止し、ログ末尾のバックアップを取り、それも適用します
  • prod DBをドロップし、新しく復元したDBの名前を変更して、prodにする
  • 製品アプリを起動

誰かがこのアプローチに穴を開けてくれませんか?多分、別のアプローチを提案しますか?必要なのは、最小限のダウンタイムです。

SQL 2000 DBサイズ94 GB破損したページがあるテーブルには、4億6,000万行以上のデータがあります。

助けてくれてありがとう。

ラージ


1
私はあなたのアプローチが好きです。私には理にかなっています。おそらく、保険として損傷したデータベースを並べておく...
user24161

また、状況が落ち着いたら、2008年または2008年のアップグレードを計画します:-)
user24161

(つまり、2005年または2008年のアップグレード)
user24161 2010

+1は有効で非常に適切な復旧計画を持っていること
Andrew

回答:


2

あなたの回復ソリューションは、続行するためのテキストブックの方法です。適切なバックアップがあり、破損したデータベースのトランザクションログをバックアップできる場合、戦略はテキストブックに実装することです。

ただし、続行する前に、影響を受けるテーブルのみを再作成する可能性を検討しましたか?

ときどき、影響を受けるテーブルの正確なコピーを作成して、

select *
into NewTableFromOld
from DamagedTable

次に、破損したテーブルを新しいテーブルにドロップ/スワップし、適切な制約とインデックスを追加することを忘れないでください。


ご回答ありがとうございます。あなたのアプローチは良さそうですが、懸念は、テーブルに4億6,100万行のデータがあることを考えると、select *を実行すると、本番環境にどのような影響がありますか?それはロックを取得してパフォーマンスをヒットしないのではないでしょうか?

with(nolock)クエリヒントnoを使用する場合はそうではありません。ただし、コピーを作成している間、ソーステーブルとターゲットテーブルの間で何も変更されていないことを検証したい場合があります。とにかく、アプリの変更を停止しなかった場合は、テーブルのビルド中にこれが必要になる可能性があります。このような操作では、ディスクパフォ​​ーマンスのオーバーヘッドが発生します。
John Sansom、2010

個人的に私は最初にこのアプローチを試します。テストのためにnolockオプションでそれを行うことができ、必要な時間もチェックすることができます。正常に機能する場合は、プロセスの実行中に変更が発生しないことを確認するために、dbを再度シングルユーザーモードにします。このアプローチでは、機能する場合、ダウンタイムははるかに短くなります。
Baldy

これを行う場合は、最初にテーブルを作成することをお勧めします(元のテーブルをスクリプト化して)。次に、「INSERT INTO newTable SELECT」と「SELECT INTO」を使用します。「SELECT INTO」を使用すると、パフォーマンスの問題が発生する可能性があります。
SQL3D 2011年

0

最初にファイルにデータをバルクアウトしてから、新しいテーブルにバルクインして戻します。SELECT INTOはその数のレコードには適切ではありません(IMO)...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.