大規模な削除クエリがフリーズしているようです


10

18億行のデータベースで削除クエリを実行しました。この削除により、12億行が削除されます。

後から考えて、このクエリを一度に100mに分割したはずですが、24時間実行されていて、ログファイルがログファイルに許可されている最大サイズである2Tbの位置にいます。

データベースは単純復旧モードです。

このクエリを保存するものはありますか?または、SQL Serverを再起動して何が起こるかを確認する必要がありますか?データベースは使用できなくなりますか?これをできるだけきれいに殺すために私たちにできることはありますか?


SSMSから実行しましたか?キャンセルしてください。キャンセルにはしばらく時間がかかります。それが実行されている限り、長い間のように。あなたは我慢する必要があります。
パパラッツォ

1
@Graeme数十億レコードのデータベースでの経験(いくつかを実行しています)から、被害者テーブルから残りのレコードを保存し、それを切り捨て、削除し、保存したレコードの名前を元の名前に戻し、インデックスがあればそれを復元する方が速い場合があります。
アントンクルーグロフ2017年

1
このspidをクリアしたら、100mよりはるかに小さいバッチをお勧めします。通常は100kから1mです。また、可能な場合は、主キーをWHERE句として使用して、削除するレコードを選択します。
BradC 2017年

Truncateは、大量のデータを削除し、ログの問題を回避しようとするときの友です。
Jeff.Clark 2017年

回答:


14

まず、SQLエラーログをチェックして、ログの最大サイズに実際に達しているかどうかを確認します。存在する場合、クエリは完了の見込みがなく、おそらくすでにロールバック状態にあります。

たとえそうであったとしても、私は常に手動でspidをkillすることを好みます(sidを使用sp_who2またはsp_WhoIsActive検索してからkill 59、何かを実行します)。また、明示的なKILLを実行しない限り、ロールバックステータスを確認することもできません。この関連スレッドを参照してください

これは削除であり、更新や挿入ではないため、非常に幸運であり、すぐにロールバックされることがわかります。そうでない場合は、この時点までにロールバックするのと同じくらい長い(または長い)時間がかかる場合があります。

ロールバックステータスを表示するには、次を使用します。

kill 59 with statusonly

残念ながら、私はこれがしばしば「0%完了」であるだけで、有用なものを何も示さないことを発見しました。その場合はsp_who2、IOとCPUを使用して監視し、まだ何かを実行しているかどうかを確認する必要があります。

再起動に関しては、これは重大なリスクです。spidがアクティブにロールバックしている(CPUとIOが変化している)場合、SQLを再起動しても、ロールバックが完全に完了するまで(数時間)データベースは完全にオフラインになります。ただし、CPUとIOが動いていない場合は、実際にはすぐにクリアされる可能性があります。いずれにしても、それはリスクです。

特に悲惨な場合の最後のオプションの1つ:削除を開始する直前のバックアップがある場合(および、データベースに他の更新がない場合)、回復する最も速い方法は、単にDBを削除して再起動することです。 SQL、バックアップからの復元。

DBをドロップできない場合(またはインスタンスをすでに再起動していて、SQLエラーログが24時間の復旧時間を予測している場合)、SQLサービスをシャットダウンし、ディスクからMDFファイルとLDFファイルを削除して、SQLを起動し、ドロップします(ゴースト)データベース、およびバックアップからの復元。

明らかに、これがユーザーが操作しなかったバックエンド処理データベースである場合にのみ試行します。


3
復元オプションについての良いアドバイス。地獄のように怖いですが、それでも良いアドバイスです。
マックスヴァーノン

2
はい、この状態でDBAにインスタンスを再起動してもらいました。そのため、18〜24時間ダウンするか、クエリが開始する前にロールバックしてデータを失うという2つの非常に悪いオプションを決定せざるを得ませんでした。ビジネスはロールバックを選択しました。
BradC 2017年

1
3月4日からの完全バックアップがあり、再起動が機能しない場合の最後の手段として復元します。幸いなことに、これは、十分に静的なDBであり、削減したかっただけです。フィードバックをありがとう、とても役に立ちました
Graeme

4
@Graeme-FYI-12億行を削除しようとする代わりに、テーブル構造のコピーを作成し、保持したい行を新しいテーブルにコピーしてから、古いテーブルを削除します。方法を尋ねる新しい質問を追加すると、12億行を削除するよりもはるかに高速な非常に洗練された方法を示すことができます。
Max Vernon

私の答えは、dbがSIMPLEリカバリモードであることを前提としています。FULLモードの場合は、巨大なtranログのバックアップも管理する必要があります。
BradC

8

SQLサーバーを再起動しないでください。回復が行われるため、これは苦痛を長引かせるだけであり、削除を含め、完了していないトランザクションをロールバックまたはやり直します。

削除を実行しているセッションを強制終了すると、ロールバックが発生し、完了までに長い時間がかかります。

次のクエリを見て、操作の状態を確認します。

SELECT des.session_id 
    , des.host_name
    , des.login_name
    , der.command
    , der.estimated_completion_time
    , der.blocking_session_id
    , der.last_wait_type
    , der.percent_complete
    , der.start_time
    , der.status
    , der.wait_resource
    , der.wait_type
    , der.wait_time
FROM sys.dm_exec_sessions des
    INNER JOIN sys.dm_exec_requests der ON des.session_id = der.session_id
WHERE des.session_id <> @@SPID
    AND des.is_user_process = 1
ORDER BY des.session_id;

percent_completeカラム、それに依拠するものは、このようなestimated_completion_time、唯一の次の操作のために取り込まれます。

ALTER INDEX REORGANIZE
AUTO_SHRINK option with ALTER DATABASE
BACKUP DATABASE
DBCC CHECKDB
DBCC CHECKFILEGROUP
DBCC CHECKTABLE
DBCC INDEXDEFRAG
DBCC SHRINKDATABASE
DBCC SHRINKFILE
RECOVERY
RESTORE DATABASE
ROLLBACK
TDE ENCRYPTION

そのため、削除ステートメントを既にキャンセルしてロールバックしている場合、またはSQL Serverを既に再起動していて復旧中である場合にのみ、その列が意味を持つことがわかります。

blocking_session_id列に数値が含まれている場合は、他のセッションが削除操作をブロックしていることを示しています。そのセッションが開始してから削除操作をブロックしている場合は、ロールバックを実行する必要なく操作をキャンセルできる場合があります。


クエリは適切ですが、削除がブロックされていた場合、ログが非常に大きくなることはほとんどありません。
BradC 2017年

4
はい。出力を少し説明しようとしています。将来の読者もこれを見るかもしれません。実際、次のOPからの連絡がないかと思います。彼は多分かなり忙しいでしょう。
Max Vernon
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.