2019年2月20日水曜日

MSSQLのDBが破損した模様

何かの理由で利用中パッケージソフトで新規登録ができなくなった模様。
※パッケージの問題ではない。と先にお伝えしておきます。

原因がDBだったので、問題を調べて、対処、処置まで完了したのでメモしておきます。

事の経緯

データを新規登録できなくなった。と連絡を受けました。
よく聞くと、登録ボタンを押すと「強制終了してしまう」との事
エラー内容を見る限りたぶんDB周りだろうな。と思い調査を開始しました。
ひとまず見つけたのはWindowsのアプリケーションログ。
「インデックスが壊れている可能性があります。DBCC CHECKDB を実行してください。」と出ていました

MSSQLのチェックツール


詳しい解説は以下サイトを参考としました。
https://www.ipentec.com/document/sql-server-db-repair-and-validation-with-dbcc-command
参考にしながら処置を実施

DBCC CHECKDB
GO

チェック結果を確認


メッセージ 8935、レベル 16、状態 1、行 1
テーブル エラー: オブジェクト ID 1413580074、インデックス ID 1、パーティション ID 72057594063093760、アロケーション ユニット ID 72057594068664320 (型 In-row data)。ページ (1:503) の前ページへのリンク (1:1503) は、親 (1:377)、スロット 31 がこのページに対して想定している前ページ (1:3646) と一致しません。
メッセージ 8978、レベル 16、状態 1、行 1
テーブル エラー: オブジェクト ID 1413580074、インデックス ID 1、パーティション ID 72057594063093760、アロケーション ユニット ID 72057594068664320 (型 In-row data)。ページ (1:503) に前ページ (1:1503) からの参照がありません。チェーン リンケージに問題がある可能性があります。
メッセージ 8935、レベル 16、状態 1、行 1
テーブル エラー: オブジェクト ID 1413580074、インデックス ID 1、パーティション ID 72057594063093760、アロケーション ユニット ID 72057594068664320 (型 In-row data)。ページ (1:1503) の前ページへのリンク (1:3646) は、親 (1:377)、スロット 84 がこのページに対して想定している前ページ (1:1251) と一致しません。
メッセージ 8936、レベル 16、状態 1、行 1
テーブル エラー: オブジェクト ID 1413580074、インデックス ID 1、パーティション ID 72057594063093760、アロケーション ユニット ID 72057594068664320 (型 In-row data)。B-Tree チェーン リンケージが一致しません。(1:1251)->next = (1:1503)、(1:1503)->Prev = (1:3646)。
メッセージ 8979、レベル 16、状態 1、行 1
テーブル エラー: オブジェクト ID 1413580074、インデックス ID 1、パーティション ID 72057594063093760、アロケーション ユニット ID 72057594068664320 (型 In-row data)。ページ (1:1752) に、親 (不明) ノードと前 (ページ (1:376)) ノードからの参照がありません。システム カタログのルート エントリが不適切である可能性があります。
メッセージ 8934、レベル 16、状態 1、行 1
テーブル エラー: オブジェクト ID 1413580074、インデックス ID 1、パーティション ID 72057594063093760、アロケーション ユニット ID 72057594068664320 (型 In-row data)。ページ (1:3645) (レベル 0) のキーの最高値が、次のページ (1:1753) の親 (0:1)、スロット 0 のキーの最低値より大きくなっています。
メッセージ 8977、レベル 16、状態 1、行 1
テーブル エラー: オブジェクト ID 1413580074、インデックス ID 1、パーティション ID 72057594063093760、アロケーション ユニット ID 72057594068664320 (型 In-row data)。ページ (1:1753) の親ノードが見つかりませんでした。
'table_xxxxxxxxx' の DBCC 結果。
オブジェクト "table_xxxxxxxxx" の 95 ページには 784 行あります。
CHECKDB により、テーブル 'table_xxxxxxxxx' (オブジェクト ID 1413580074) に 0 個のアロケーション エラーと 7 個の一貫性エラーが見つかりました。

エラー出ました。(table_xxxxxxxxの部分は実テーブル名を置き換えて表示しています)

参考サイトに従ってリペアを実施



ALTER DATABASE '対象のデータベース名' SET SINGLE_USER
GO
DBCC CHECKDB('対象のデータベース名','REPAIR_REBUILD')
GO
ALTER DATABASE "対象のデータベース名" SET MULTI_USER
GO
ALTER DATABASE "対象のデータベース名" SET RECOVERY FULL
GO


再テスト 


DBCC CHECKDB
GO


変わらず。と。

インデックスの違反なんだろうから、インデックスを再構築してしまえとも
思うんだけどもテーブル定義を見てみても、Primaryしかない
なんだかなぁ。なので、以下にチャレンジ

無理やりテーブルを再作成してみる

ざっくり言うと、別のテーブルへ移して、リネームして戻してしまえ。

1.エラーが出ているテーブル(A)をselect into で別テーブル(B)へ
2.テーブル(A)をリネーム
3.テーブル(B)をテーブル(A)へリネーム

これでパッケージソフト上でのエラーは出なくなりました。

修復できたようなので後片付け

おそらくですが、テーブル(A)のPrimaryが壊れたのだろうと推測。
→後の処置で確かに存在しえないデータが複数selectできたのでそれ。
クリアできたので、改めて以下処置を実施

ざっくり言うと、定義は生かして、今のを退避して、テーブル再構築、データ再投入

1.上記のテーブル(A)からDDLを取得
2.上記テーブル(A)をリネームし、Primaryを削除 
→これをしないとPrimaryの名称が被ったため
3.取得したDDLにてテーブルを作成
4.上記2)でリネームしておいたデータから、3)で作成したテーブルへデータを流す

作業を終えてから

DBCC CHECKDB
GO
でエラーが消えたことを確認しました

1 件のコメント:

Ryo Kaneko さんのコメント...

処置から3ヶ月ほど経過しましたが、同様のトラブル、関連トラブルもないので完全解決です