web-dev-qa-db-ja.com

SQL Serverミラーリングデータベースでのデータベース破損の検出と修正

私は現在の会社に初めて参加し、システム管理者はいますが、DBAはいません。以前は、他の会社でDBA関連の問題を担当していました。他のデータベース(FoxproとAccess)でデータベースの破損に遭遇して修正し、少なくとも破損したデータを記録して再入力できるようにしました。 SQL Serverデータベースでの破損に遭遇したり、破損した疑いはありません。ミラーリングされているSQL Server 2005データベースでこれに遭遇していると思います。

データベースに渡された単純な削除コマンドが特定のテーブルのデータを削除していない状況です。文字通り、SQL Server Management Studioにアクセスし、deleteコマンドを発行して、これらのテーブルをクリアする必要があります。一時テーブルには144千から3200万のレコードがあり、このデータはデータベースの90%以上を占めています(レコードを削除してデータベースを圧縮した後で決定)。これをクリーンアップした後、テストサーバーのデータベースに渡された削除コマンドが機能します。

最初の攻撃は、データベースのコピーに対してDBCC CHECKDBを実行することです。バックアップに対して実行したところ、破損は見つかりませんでした。私のシステム管理者は、データベースサーバーがオンラインになるまでに最大6時間かかり、稼働中のSQLサーバーとミラーリングされたSQLサーバーの両方を無効にしたくないという問題を抱えていたため、データベースの正確なコピーを取得できません。

最初の質問は、データベースのバックアップを信頼して、DBCC CHECKDBによって検出される破損したデータを含める必要があるかどうかです。バックアップに破損が保存されていない場合、ライブデータベースとミラーデータベースの両方を停止してから復元し、LDFとMDFファイルのコピーを取得するには、どの方法が最適ですか?

最後に、テストで破損を見つけた場合、破損を示す可能性のあるページのコンテンツをどのように判断しますか?

2
Jim

あなたが見ているものが腐敗である可能性はほとんどありません。

この問題のはるかに考えられる原因は、「アプリ」がDELETE FROMコマンドを正しく発行していないか、またはあなたが思っている方法で発行していないことです。おそらく [〜#〜] delete [〜#〜] が何らかの理由でロールバックされているか、またはWHEREステートメントが、削除する必要があると思われる行の削除を妨げている可能性があります。アプリでコードを表示できる場合は、 を介して、DELETEを実行している(またはしない実行している)コードを質問に追加します編集 リンク。コードにアクセスできない場合は、 SQL Server Profiler を使用してトレースを実行し、アプリがサーバーに発行しているステートメントを「確認」して、アプリの内容を特定できます。 やっています。

アプリケーションレベルのデータの問題が原因で、アプリケーションが削除を実行できない可能性があります。たとえば、参照整合性を適用する主キー/外部キーの関係がない場合、行が孤立する結果として行が削除されないように、DELETE FROMステートメントが削除で結合を使用している可能性があります。例として、これを見てください:

USE tempdb;

IF OBJECT_ID(N'dbo.Child', N'U') IS NOT NULL
DROP TABLE dbo.Child;
IF OBJECT_ID(N'dbo.Parent', N'U') IS NOT NULL
DROP TABLE dbo.Parent;

CREATE TABLE dbo.Parent
(
    parent_id int NOT NULL
        CONSTRAINT Parent_pk
        PRIMARY KEY CLUSTERED
    , parent_data varchar(50) NOT NULL
);

CREATE TABLE dbo.Child
(
    child_id int NOT NULL
        CONSTRAINT Child_pk
        PRIMARY KEY CLUSTERED
    , parent_id int NOT NULL
    , child_data varchar(10) NOT NULL
);

INSERT INTO dbo.Parent (parent_id, parent_data)
VALUES (1, 'A')
    , (2, 'B');

INSERT INTO dbo.Child (child_id, parent_id, child_data)
VALUES (1, 1, 'C')
    , (2, 1, 'D')
    , (3, 2, 'E')
    , (4, 2, 'F')
    , (5, 3, 'G')
    , (6, 3, 'H');

SELECT *
FROM dbo.Child;
╔══════════╦═══════════╦════════════╗
║child_id║ parent_id║child_data║
╠══════════╬═══════════╬════════════╣
║1║1║C║
║2║1║D║
║3║2║E║
║4║2║F║
║ 5║3║G║
║6║3║H║
╚══════════╩═══════════╩═══ ═════════╝

ここで、dbo.Childからすべての行を削除する場合は、次の削除ステートメントを使用して、親テーブルに親を持つすべての子行を削除できます。

DELETE FROM dbo.Child
FROM dbo.Child c
INNER JOIN dbo.Parent p ON c.parent_id = p.parent_id;

dbo.Childテーブルに適切に定義された外部キーがある場合、5番目と6番目の行は存在できませんが、適切なリレーショナル整合性がないため、次のような子テーブルに行が存在する可能性があります。このSELECTステートメントからわかるように、上記の削除の実行後に実行された親はありません。

SELECT *
FROM dbo.Child;
╔══════════╦═══════════╦════════════╗
║child_id║parent_id║child_data║
╠══════════╬═══════════╬════════════╣
║5║3 ║G║
║6║3║H║
╚══════════╩═══════════╩══════ ══════╝

SQL Serverがプライマリデータベース(現在オンラインでクライアントにサービスを提供しているデータベース)の破損を検出すると、破損したページをミラーデータベースから 自動ページ修復 を介して転送します。データベースの自動修正を試みます。自動ページ修復は、SQL Server 2005 Service Pack 1から利用可能になり、ミラーリングが正式にサポートオプションになりました。

DBCC CHECKDBを実行して破損が報告されていないため、破損が発生していないとはほぼ100%確実です

2
Max Vernon

データベースに渡された単純な削除コマンドが特定のテーブルのデータを削除していない状況です。文字通り、SQL Server Management Studioにアクセスし、deleteコマンドを発行して、これらのテーブルをクリアする必要があります。

これによりデータベースが破損していると思われる場合は、正しくないと考えています。データベースが破損していることをどのように確認していますか。私はあなたが投稿したものをそのまま使っています

最初の質問は、データベースのバックアップを信頼して、DBCC CHECKDBによって検出される破損したデータを含める必要があるかどうかです。バックアップに破損が保存されていない場合、ライブデータベースとミラーデータベースの両方を停止してから復元し、LDFとMDFファイルのコピーを取得するには、どの方法が最適ですか?

破損について最も重要なことは、なぜ発生し、何が原因であるかです。バックアップが破損していない場合、その場合、同じ名前の別のサーバーにデータベースを復元する必要があります。基盤となるサブシステムが非常に破損している場合、新しく復元されたデータベースも破損する可能性もあります。ミラーデータベースも破損している可能性があります。それ以外の場合は、ミラーデータベースにフェールオーバーして(復元を並行して実行しているときに)、動作するかどうかを確認できます。

最後に、テストで破損を見つけた場合、破損を示す可能性のあるページのコンテンツをどのように判断しますか?

これは、破損のレベルと、dbcc checkdbコマンドを実行した理由によって異なります。運が良ければ、どのページ(ページID)とインデックス(CI、NCI)が実際に壊れているかを示す結果が生成されますが、これを回避するにはエキスパートが必要になる場合があります。

sp_readerrorlogとイベントビューアを使用してSQL Serverエラーログを読み取ると、破損に関するより多くの情報が得られます。ほとんどの場合、破損したディスクサブシステムが破損したSQL Serverデータベースの原因です

道徳:すべてのものは腐敗のレベルに依存します。 repair_rebuildコマンドを実行するだけで削除できる破損はほとんどありません。

0
Shanky