Permintaan penghapusan besar tampaknya telah dibekukan

10

Kami menjalankan kueri penghapusan pada basis data dengan baris 1,8 miliar. Penghapusan ini akan menghapus baris 1,2 miliar.

Jika dipikir-pikir, kami akan memecah kueri ini menjadi 100 m pada satu waktu tetapi kami berada dalam posisi di mana ia telah berjalan selama 24 jam dan file log pada 2TB yang tampaknya merupakan ukuran maksimum yang diizinkan untuk file log.

Basis data dalam mode pemulihan SEDERHANA.

Apakah ada yang menyimpan kueri ini? Atau apakah kita perlu me-restart SQL Server dan melihat apa yang terjadi? Apakah basis data tidak dapat digunakan? Adakah yang bisa kita lakukan untuk membunuh ini sebersih mungkin?

Graeme
sumber
Apakah Anda menjalankannya dari SSMS? Batalkan saja. Perlu beberapa saat untuk membatalkan. Seperti sekitar selama itu telah berjalan. Anda harus bersabar.
paparazzo
1
@Graeme Dari pengalaman kami dengan miliaran catatan database (kami menjalankan beberapa dari mereka) terkadang lebih cepat untuk menyimpan catatan yang tersisa dari tabel korban, memotongnya, menghapusnya, mengganti nama catatan yang disimpan kembali ke nama asli dan kemudian mengembalikan indeks jika ada .
Anton Krouglov
1
Setelah Anda membersihkan spid ini, saya akan merekomendasikan batch yang jauh lebih kecil dari 100m, saya biasanya melakukan 100k hingga 1m. Juga, gunakan kunci utama Anda sebagai klausa WHERE Anda untuk memilih catatan untuk dihapus, jika memungkinkan.
BradC
Truncate adalah teman Anda saat menghapus data dalam jumlah besar dan berusaha menghindari masalah log.
Jeff.Clark

Jawaban:

14

Pertama-tama, periksa SQL errorlog untuk melihat apakah itu benar-benar mencapai ukuran maksimal untuk log. Jika ya, maka kueri tidak memiliki harapan untuk menyelesaikan, itu mungkin sudah dalam keadaan rollback.

Bahkan jika ya, saya selalu lebih suka membunuh spid secara manual (gunakan sp_who2atau sp_WhoIsActiveuntuk menemukan spid, lalu lakukan kill 59atau apa pun). Anda juga tidak dapat memeriksa status rollback kecuali jika Anda melakukan KILL eksplisit, lihat utas terkait ini .

Karena ini adalah penghapusan, dan bukan pembaruan atau penyisipan, Anda mungkin sangat beruntung dan menemukannya segera kembali. Jika tidak, mungkin diperlukan selama (atau lebih lama) untuk memutar kembali seperti yang dilakukan untuk sampai ke titik ini.

Untuk melihat status rollback, gunakan

kill 59 with statusonly

Sayangnya, saya menemukan ini sering tidak menunjukkan sesuatu yang berguna, hanya "0% selesai". Dalam hal ini, Anda harus menggunakan sp_who2dan menonton IO dan CPU untuk melihat apakah masih melakukan sesuatu.

Mengenai reboot, ini adalah risiko besar. Jika spid diaktifkan kembali secara aktif (CPU dan IO berubah), maka restart SQL hanya akan membuat database offline sepenuhnya sampai rollback sepenuhnya selesai (jam dan jam). Tetapi , jika CPU dan IO tidak bergerak, maka itu mungkin akan langsung menghapusnya. Bagaimanapun, itu adalah risiko.

Satu opsi terakhir, jika semuanya sangat mengerikan: Jika Anda memiliki cadangan tepat sebelum penghapusan dimulai (dan belum ada pembaruan lain untuk db) , maka cara tercepat untuk memulihkan mungkin dengan hanya menjatuhkan DB, mulai ulang SQL, dan pulihkan dari cadangan.

Jika Anda tidak dapat menjatuhkan DB (atau jika Anda telah memulai kembali instance dan sql errorlog memperkirakan waktu pemulihan 24 jam), kemudian matikan layanan SQL, hapus file MDF dan LDF dari disk, mulai SQL, drop database (hantu), dan pulihkan dari cadangan.

Jelas Anda hanya akan mencoba jika ini adalah database pemrosesan back-end yang tidak berinteraksi dengan pengguna.

BradC
sumber
3
Saran bagus, tentang opsi pemulihan. Menakutkan sekali, tapi tetap saja saran yang bagus.
Max Vernon
2
Yap, kami memiliki DBA memulai kembali instance dalam kondisi ini, yang memaksa kami untuk memutuskan antara dua opsi yang sangat buruk: turun selama 18-24 jam, atau kehilangan data dengan memutar kembali ke sebelum pertanyaan dimulai. Bisnis memilih untuk mundur.
BradC
1
Kami memiliki cadangan lengkap mulai 4 Maret yang akan kami pulihkan sebagai upaya terakhir jika reboot tidak berfungsi. Untungnya itu adalah DB yang cukup statis yang kami hanya ingin memangkas. Terima kasih atas umpan baliknya, sangat membantu
Graeme
4
@Graeme - FYI - alih-alih mencoba menghapus 1,2 miliar baris, buat salinan struktur tabel, salin baris yang ingin Anda simpan di tabel baru, lalu jatuhkan tabel lama. Jika Anda menambahkan pertanyaan baru yang menanyakan cara melakukannya, saya dapat menunjukkan kepada Anda cara yang sangat licin yang jauh lebih cepat daripada menghapus 1,2 miliar baris.
Max Vernon
Jawaban saya mengasumsikan db berada dalam mode pemulihan SEDERHANA. Jika dalam mode LENGKAP, Anda juga harus mengelola cadangan tran log yang besar.
BradC
8

JANGAN RESTART SQL SERVER. Ini hanya akan memperpanjang penderitaan Anda karena pemulihan akan terjadi, yang akan mengembalikan atau mengulangi transaksi yang tidak selesai, termasuk penghapusan Anda.

Membunuh sesi yang menjalankan penghapusan akan menghasilkan rollback yang terjadi, yang juga membutuhkan waktu lama untuk diselesaikan.

Anda ingin melihat kueri berikut untuk melihat keadaan operasi:

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;

The percent_completekolom, dan orang-orang yang bergantung pada itu, seperti estimated_completion_time, hanya dihuni untuk operasi berikut:

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

Jadi, Anda hanya akan melihat kolom itu bermakna jika Anda sudah membatalkan pernyataan penghapusan, dan itu bergulir kembali, atau jika Anda sudah memulai ulang SQL Server dan sedang dalam pemulihan.

Jika blocking_session_idkolom berisi angka, itu menunjukkan bahwa sesi lain memblokir operasi penghapusan. Jika sesi itu telah memblokir operasi penghapusan sejak dimulai, Anda mungkin dapat membatalkan operasi tanpa perlu mengembalikan.

Max Vernon
sumber
Kueri yang bagus, tetapi tampaknya log tidak mungkin tumbuh besar jika penghapusan diblokir.
BradC
4
Iya. Saya hanya mencoba menjelaskan output sedikit. Pembaca masa depan juga dapat melihat ini. Bahkan, saya ragu apakah kita akan mendengar dari OP di saat berikutnya. Dia sepertinya cukup sibuk.
Max Vernon