Apakah memutus jaringan menghentikan permintaan?

13

Saya baru-baru ini menjalankan permintaan pembaruan terhadap 100.000 catatan. Saya menyadari bahwa saya telah membuat kesalahan ketika permintaan sedang berjalan dan dengan cepat mencabut kabel jaringan.

Apakah permintaan pembaruan

  1. hentikan pemrosesan dan kembalikan sepenuhnya?
  2. lanjutkan pemrosesan hingga selesai dan komit?
  3. hentikan pemrosesan dan biarkan hanya sebagian dari baris target yang diperbarui?
Robocop
sumber
2
setelah kueri mencapai server, kueri akan dilanjutkan kecuali jika Anda membatalkan kueri di server.
JP Chauhan
1
Komentar Martin memberikan jawaban langsung untuk pertanyaan Anda, robocop. Jika jaringan memberitahu SQL Server tentang pemutusan sebelum permintaan Anda selesai berjalan, maka SQL Server akan mengembalikannya. Jika tidak, jika permintaan selesai sebelum SQL Server diberitahu ada putuskan jaringan, maka akan dilakukan. Dalam kasus apa pun (dengan asumsi Anda menulis permintaan pembaruan tunggal) SQL Server akan menjalankan pembaruan parsial.
Nick Chammas

Jawaban:

22

Seperti yang disebutkan oleh Nick dan Martin, status akhir kueri Anda bergantung pada apakah SQL Server mengetahui tentang penarikan kabel jaringan Anda sebelum kueri selesai. Dari Books Online (meskipun saya merasa menarik bahwa ada topik yang setara untuk ini pada 2000 , 2005 , 2008 , dan 2008 R2 , tetapi tidak pada 2012 atau 2014):

Jika kesalahan mencegah penyelesaian transaksi yang berhasil, SQL Server secara otomatis memutar kembali transaksi dan membebaskan semua sumber daya yang dimiliki oleh transaksi. Jika koneksi jaringan klien ke mesin database terputus, setiap transaksi yang belum dilunasi untuk koneksi tersebut dibatalkan saat jaringan memberitahukan mesin virtual tersebut. Jika aplikasi klien gagal atau jika komputer klien turun atau dinyalakan kembali, ini juga memutus koneksi, dan mesin database contoh memutar kembali setiap koneksi yang beredar ketika jaringan memberitahukan itu dari istirahat. Jika klien keluar dari aplikasi, transaksi yang ada dibatalkan.

(Sebagai tambahan, kata koneksi dalam kalimat terakhir ke-2 mungkin dimaksudkan sebagai transaksi . Saya tidak tahu bagaimana seseorang mengembalikan koneksi.)

Dengan cara yang sama, SQL Server dapat membatalkan atau mengulang transaksi selama pemulihan setelah server dimatikan secara tak terduga, dan ini akan tergantung pada keadaan transaksi pada saat penutupan. Saya telah melihat orang-orang menggunakan taktik ini untuk mencapai apa yang Anda coba lakukan (batalkan transaksi) dan ketika server mulai lagi, sebagian besar pekerjaan hanya dilakukan ulang (sehingga efek bersih dari reaksi spontan mereka lebih dekat) ke nol dari yang mereka harapkan).

Jadi, daripada tunduk pada ini, daripada melakukan hal-hal drastis dalam kepanikan, seperti mencabut kabel jaringan atau mematikan mesin, saya sarankan di masa depan Anda memiliki disiplin yang lebih baik tentang menjalankan permintaan ad hoc terhadap sistem penting. Misalnya, alih-alih:

UPDATE dbo.sometable 
-- where *oops* I forgot this part

Ambil ini:

BEGIN TRANSACTION;

UPDATE dbo.sometable
-- where *oops* I forgot this part

-- COMMIT TRANSACTION;
-- ROLLBACK TRANSACTION;

Kemudian, jika pembaruan itu memang benar, Anda dapat menyorot COMMITbagian itu dan menjalankannya. Jika tidak, Anda dapat dengan tenang menyorot ROLLBACKbagian itu dan menjalankannya. Anda bahkan dapat menggunakan peralatan tambahan seperti SSMS Tools Pack untuk mengedit New Querytemplate Anda untuk memasukkan boilerplate itu.

Sekarang itu masih bisa membuat Anda dalam masalah jika Anda menjalankan kueri dan kemudian jangan melakukan komit atau kembalikan, karena sekarang transaksi Anda memblokir pengguna lain. Tapi ini lebih baik daripada memodifikasi data yang tidak dapat dibatalkan.

Dan tentu saja, seperti biasa, punya cadangan yang bisa Anda andalkan.

Aaron Bertrand
sumber
5
Ini adalah saran yang bagus dan membahas akar masalah OP, tetapi sebenarnya tidak menjawab pertanyaan apakah kueri terus berjalan atau tidak.
Nick Chammas
3
Terima kasih @Nick, motivasi saya adalah untuk mengatasi penyebabnya (yang memicu pertanyaan), bukan gejalanya, tapi saya sudah memperbarui jawaban saya.
Aaron Bertrand
8

@ Harun benar. Membuat transaksi sebelum perintah Anda adalah taruhan terbaik Anda. Jika Anda tidak ingat untuk melakukan itu maka satu opsi adalah masuk ke Tools-Optionspengaturan dan nyalakan SET IMPLICIT_TRANSACTIONS. Ini akan secara otomatis memulai transaksi segera setelah perintah tertentu dijalankan. Ini termasuk UPDATE, DELETEdll. Ini tampaknya daftar yang cukup lengkap dari perintah apa pun yang akan menghasilkan "change"sesuatu. SELECTjuga termasuk dalam daftar dan willmemulai transaksi. Anda dapat melihat daftar lengkap perintah yang memulai transaksi akan pengaturan ini di sini . Itu tidak akan membuat transaksi jika sudah dimulai. Sekarang sisi negatifnya adalah Anda harus mengingat COMMITsetelah perubahan apa pun dilakukan.

CATATAN: Berdasarkan saran @ Harun saya akan menekankan kembali ini.

This is very important!  You will have to remember to COMMIT after any change made!

Pada dasarnya Anda menjual lupa untuk BEGINsuatu transaksi dan mengacaukan sesuatu, untuk lupa untuk COMMITtransaksi dan setelah itu tergantung jika Anda membiarkannya terbuka dan kemudian pergi untuk hari itu. Saya memang menguji hanya menutup jendela permintaan berpikir itu akan memutar kembali transaksi saya, namun itu meminta saya jika saya ingin melakukan atau mengembalikan transaksi.

masukkan deskripsi gambar di sini

Kenneth Fisher
sumber
Sebenarnya: SELECT akan memulai transaksi (yang juga didokumentasikan dalam tautan yang Anda poskan)
a_horse_with_no_name
Terima kasih @a_horse_with_no_name untuk menangkapnya! Saya tidak membaca dengan cukup hati-hati dan pergi dari memori lama (itu jelas salah).
Kenneth Fisher
1
Ini adalah posting yang bermanfaat, tetapi sebenarnya tidak menjawab pertanyaan OP apakah kueri terus berjalan atau tidak.
Nick Chammas
2
Itu dimaksudkan sebagai tambahan pada jawaban @ Aaron. Itu hanya banyak untuk dimasukkan ke dalam komentar.
Kenneth Fisher
2

saya pikir itu sangat tergantung:

jika perintah sudah mencapai server sebelum Anda mencabut kabel jaringan, perintah masih akan terus berjalan secara normal.

jika Anda memiliki TransactionScope (digunakan dalam .Net, tidak yakin bahasa lain) untuk merangkum semua perintah pembaruan, Anda mungkin dapat menghentikan transaksi yang hanya akan dilakukan jika transactionScope.Complete () belum dijalankan, tetapi tidak ada jaminan .. .

Rex
sumber
2
Anda berkata "jika perintah sudah mencapai server sebelum Anda mencabut kabel jaringan, perintah itu akan tetap berjalan secara normal." Ini bertentangan dengan halaman BOL SQL Server yang ditautkan Martin ke atas. Lihat "Kesalahan Selama Pemrosesan Transaksi" .
Nick Chammas
kamu benar. dengan transaksi yang ditentukan, perintah akan memutar kembali secara otomatis. tetapi seperti yang kami alami, ketika tidak ada transaksi yang ditentukan secara eksplisit, perintah (pembaruan batch tanpa transaksi) dieksekusi sepenuhnya bahkan kami menghentikan aplikasi kami di tengah, yang benar-benar memutuskan koneksi - tetapi itu bukan contoh yang baik sebagai waktu mungkin tidak benar. mungkin ada baiknya melakukan beberapa pengujian untuk itu
Rex