Hari ini saya menemukan harddisk yang menyimpan basis data saya penuh. Ini pernah terjadi sebelumnya, biasanya penyebabnya cukup jelas. Biasanya ada permintaan yang buruk, yang menyebabkan tumpahan besar untuk tempdb yang tumbuh hingga disk penuh. Kali ini agak kurang jelas apa yang terjadi, karena tempdb bukan penyebab drive penuh, itu adalah database itu sendiri.
Fakta:
- Ukuran basis data yang biasa sekitar 55 GB, itu tumbuh menjadi 605 GB.
- File log memiliki ukuran normal, datafile sangat besar.
- Datafile memiliki 85% ruang yang tersedia (saya menafsirkan ini sebagai 'udara': ruang yang digunakan, tetapi telah dibebaskan. SQL Server cadangan semua ruang yang pernah dialokasikan).
- Ukuran Tempdb normal.
Saya telah menemukan kemungkinan penyebabnya; ada satu kueri yang memilih terlalu banyak baris (bergabung dengan buruk menyebabkan pemilihan 11 miliar baris di mana beberapa ratus ribu diharapkan). Ini adalah SELECT INTO
permintaan, yang membuat saya bertanya-tanya apakah skenario berikut bisa terjadi:
- SELECT INTO dieksekusi
- Tabel target dibuat
- Data dimasukkan saat dipilih
- Disk terisi, menyebabkan insert gagal
- SELECT INTO dibatalkan dan dibatalkan
- Rollback membebaskan ruang (data yang sudah dimasukkan dihapus), tetapi SQL Server tidak merilis ruang yang dibebaskan.
Dalam situasi ini, bagaimanapun, saya tidak akan mengharapkan tabel yang dibuat oleh SELECT INTO
masih ada, itu harus dijatuhkan oleh rollback. Saya menguji ini:
BEGIN TRANSACTION
SELECT T.x
INTO TMP.test
FROM (VALUES(1))T(x)
ROLLBACK
SELECT *
FROM TMP.test
Ini menghasilkan:
(1 row affected)
Msg 208, Level 16, State 1, Line 8
Invalid object name 'TMP.test'.
Namun tabel target memang ada. Namun, kueri aktual tidak dieksekusi dalam transaksi eksplisit, dapatkah itu menjelaskan keberadaan tabel target?
Apakah asumsi yang saya buat di sini benar? Apakah ini skenario yang mungkin terjadi?