今日、データベースを保存するハードドライブがいっぱいであることを発見しました。これは以前にも起こりましたが、通常、原因は非常に明白です。通常、不適切なクエリがあり、tempdbに大量の流出が発生し、ディスクがいっぱいになるまで増大します。今回は、tempdbがドライブ全体の原因ではなく、データベースそのものであるため、何が起こったのかが少しわかりにくくなりました。
事実:
- 通常のデータベースサイズは約55 GBでしたが、605 GBに増加しました。
- ログファイルのサイズは標準で、データファイルは巨大です。
- データファイルには85%の使用可能なスペースがあります(これを「空気」と解釈します:使用されたが、解放されたスペースです。SQLServerは、割り当てられるとすべてのスペースを予約します)。
- tempdbのサイズは正常です。
考えられる原因を見つけました。あまりにも多くの行を選択するクエリが1つあります(不正な結合により、数十万が予想される110億行が選択されます)。これはSELECT INTO
クエリであり、次のシナリオが発生したのではないかと思いました。
- SELECT INTOが実行されます
- ターゲット表が作成されます
- データは選択されたとおりに挿入されます
- ディスクがいっぱいになり、挿入が失敗する
- SELECT INTOは中止され、ロールバックされます
- ロールバックは領域を解放します(既に挿入されたデータは削除されます)が、SQL Serverは解放された領域を解放しません。
ただし、この状況では、によって作成されたテーブルSELECT INTO
がまだ存在することを期待していなかったため、ロールバックによって削除されるはずです。私はこれをテストしました:
BEGIN TRANSACTION
SELECT T.x
INTO TMP.test
FROM (VALUES(1))T(x)
ROLLBACK
SELECT *
FROM TMP.test
これは次の結果になります。
(1 row affected)
Msg 208, Level 16, State 1, Line 8
Invalid object name 'TMP.test'.
ただし、ターゲットテーブルは存在します。実際のクエリは明示的なトランザクションで実行されませんでしたが、ターゲットテーブルの存在を説明できますか?
ここでスケッチした仮定は正しいですか?これは起こりそうなシナリオですか?