Apakah peningkatan latensi jaringan akan menyebabkan kunci tabel di MS SQL Server?

16

Jika saya membuat satu panggilan ke database SQL Server melalui jaringan latensi tinggi, akankah kunci tabel terjadi karena latensi itu? Katakanlah saya kueri tabel A untuk beberapa catatan, dan SQL Server harus mengembalikan data itu melalui jaringan lambat - apakah akan ada kunci baca di tabel A saat server mengirim respons melalui jaringan, atau apakah SQL Server melepaskan kunci sebelum mengirim responnya?

Juga, apakah jawabannya bervariasi berdasarkan pada ukuran respons? Jika itu hanya harus mengembalikan beberapa KB vs beberapa ratus MB, apakah itu akan membuat perbedaan?

Membuat transaksi eksplisit, menjalankan kueri, dan menutup transaksi jelas akan menyebabkan tabel terkunci, karena durasi transaksi berkorelasi dengan latensi saya.

Evan M
sumber
Kecuali jika Anda menentukan nolockpetunjuk, akan selalu ada kunci . Latensi hanya menentukan berapa lama kunci akan ditahan.
Brandon
3
Dan bahkan dengan nolock, Anda masih akan mendapatkan kunci
billinkc
@ brandon Apakah itu didokumentasikan oleh Microsoft di mana saja? Pencarian saya ternyata kosong.
Evan M
1
@Brandon NOLOCK tidak berarti apa yang Anda pikirkan artinya.
Aaron Bertrand
3
@Brandon Unless you specify a nolock hint, there will always be a lock.<- ini menyiratkan jika Anda menggunakan nolock mungkin tidak ada kunci. Saya hanya mengklarifikasi.
Aaron Bertrand

Jawaban:

15

Jika klien membutuhkan waktu lama untuk menerima data dan pada gilirannya mengirim pengakuan ke SQL Server bahwa ia telah menerima data SQL Server harus menunggu, karena menunggu ini SQL Server tidak akan merilis kunci yang dipegang oleh permintaan kecuali pengakuan diterima dari klien.

Ini tidak akurat, itu tergantung pada tingkat isolasi.

Pada awalnya READ COMMITTEDkunci tidak ditahan selama durasi eksekusi pernyataan.READ COMMITTEDtidak memberikan konsistensi tingkat pembacaan pernyataan, satu-satunya jaminan adalah bahwa Anda tidak dapat membaca data yang tidak dikomit. Kunci bersama diperoleh dan ditahan untuk membaca baris dan kemudian dilepaskan.

Kecuali Anda memiliki tipe LOB.

Jenis LOB, karena berpotensi sangat besar, tidak dapat disangga. Kunci yang dibagikan harus diperoleh dan ditahan sampai pernyataan selesai, pada dasarnya memberi Anda REPEATABLE READperilaku di READ COMMITTED.

Jika saya melakukan satu panggilan ke database MSSQL melalui jaringan latensi tinggi, akankah kunci tabel terjadi karena latensi itu?

Latensi tidak menyebabkan kunci tabel, tidak. Namun, jika kunci meja telah diperoleh, latensi akan memperpanjangnya.

Mengutip seseorang yang tahu mekanisme ini lebih baik dari saya ( @RemusRusanu ):

Hasilnya dikembalikan kembali ke program klien saat eksekusi berlangsung. Sebagai baris 'gelembung' di pohon eksekusi, operator teratas biasanya ditugaskan menulis baris ini ke buffer jaringan dan mengirimkannya untuk kembali ke klien. Hasilnya tidak dibuat terlebih dahulu ke beberapa penyimpanan perantara (memori atau disk) dan kemudian dikirim kembali ke klien, melainkan dikirim kembali seperti yang sedang dibuat (saat query dijalankan). Mengirim hasil kembali ke klien, tentu saja, tunduk pada protokol kontrol aliran jaringan. Jika klien tidak secara aktif mengonsumsi hasilnya (mis. Dengan memanggil SqlDataReader.Read ()) maka pada akhirnya kontrol aliran harus memblokir sisi pengiriman (kueri yang sedang dieksekusi) dan ini pada gilirannya akan menunda eksekusi pertanyaan.[sumber]

Di mana hasil tidak dikonsumsi secepat SQL Server dapat mengirimkannya, baik itu karena klien atau jaringan, kami melihat ASYNC_NETWORK_IOmenunggu akumulasi. Untuk mengulangi, ini tidak akan mempengaruhi kunci yang diperoleh, hanya durasi mereka ditahan.

Mark Storey-Smith
sumber
9

Jawaban Mark menghilangkan banyak kebingungan saya, tetapi saya ingin memposting temuan saya setelah saya menguji ini menggunakan NetBalancer untuk meniru latensi.

Saya meminta mesin lokal saya memanggil server SQL jarak jauh dan menjalankan SELECT dan INSERT di atas meja dalam transaksi kecil. Pada mesin jarak jauh, saya terhubung ke instance SQL lokal dan menggunakan loop WHILE untuk berulang kali beralih ke tabel sys.dm_tran_locks, mencari kunci apa saja di meja yang saya modifikasi dan baca. Saya menginstal NetBalancer di server dan menggunakannya untuk meniru latensi jaringan pada koneksi jaringan server.

Inilah yang saya temukan:

  • Untuk pernyataan yang tidak mengembalikan banyak data ke klien, latensi tidak berpengaruh pada penguncian. Saya hanya mengembalikan beberapa ratus byte data paling banyak. Transaksi pada mesin saya memiliki WAITFOR 250ms yang menjaga kunci, dan ketika saya menggenjot latensi jaringan hingga 5.000 ms, durasi kunci tetap dekat dengan 250 ms.
  • Untuk pernyataan yang mengembalikan banyak data, latensi pasti berdampak penguncian, saya mengembalikan puluhan ribu baris kembali ke klien, dan tanpa latensi, durasi kunci pendek. Ketika saya meningkatkan latensi, kunci berlanjut hingga saya menerima semua data.

Dari ini, saya menyimpulkan bahwa latensi tidak masalah asalkan data sesuai dengan buffer jaringan. Jika SQL harus meletakkan banyak data dalam buffer jaringan, latensi akan membuat buffer itu untuk membuat cadangan dan SQL akan menahan kunci tabel sampai dapat menempatkan semua hasil permintaan ke buffer.

Evan M
sumber
Hasil yang menarik. Program / perpustakaan klien apa ini?
James L
Barang bagus. Apakah ada peluang Anda dapat menghabiskan lebih banyak waktu untuk hal ini dan melihat apakah Anda dapat menentukan ukuran hasil di mana hal ini terjadi?
Mark Storey-Smith
@ MarkStorey-Smith Saya tidak berpikir saya bisa mendapatkan nilai yang tepat, dan itu pasti akan berbeda di setiap mesin. Dari vircom.com/security/improve-sql-nic-performance , sepertinya ini adalah pengaturan pada NIC lokal Anda, dan yang ada di server basis data saya disetel ke 'otomatis'
Evan M
@ James, saya baru saja menggunakan SSMS di kedua mesin
Evan M
0

Jika saya melakukan satu panggilan ke database MSSQL melalui jaringan latensi tinggi, akankah kunci tabel terjadi karena latensi itu?

Ketika kueri dipecat dan diselesaikan oleh SQL Server menghasilkan hasil, letakkan di buffer output dan kirim ke klien yang kemudian mengambil hasil dari buffer Output. SQL Server tidak akan melepaskan kunci yang dipegang oleh permintaan kecuali Pengakuan diterima dari Klien. Yang mungkin menyebabkan pemblokiran.

Sunting: Evan Anda bisa merujuk ke artikel dukungan MS ini

Di bagian 3

Memblokir yang Disebabkan oleh SPID yang Aplikasi Kliennya Sesuai Tidak Menjemput Semua Baris Hasil untuk Diselesaikan

Setelah mengirim kueri ke server, semua aplikasi harus segera mengambil semua baris hasil sampai selesai. Jika suatu aplikasi tidak mengambil semua baris hasil, kunci dapat dibiarkan di atas meja, memblokir pengguna lain. Jika Anda menggunakan aplikasi yang secara transparan mengirimkan pernyataan SQL ke server, aplikasi harus mengambil semua baris hasil. Jika tidak (dan jika tidak dapat dikonfigurasi untuk melakukannya), Anda mungkin tidak dapat menyelesaikan masalah pemblokiran. Untuk menghindari masalah, Anda dapat membatasi aplikasi yang berperilaku buruk ke pelaporan atau database pendukung keputusan.

Shanky
sumber
Terima kasih atas jawaban Anda Shanky! Apakah Anda mengetahui jika ini didokumentasikan di mana saja?
Evan M
5
Ini tidak benar.
Mark Storey-Smith
Ini benar sepertinya 'aplikasi tidak mengambil semua baris hasil, kunci dapat dibiarkan di atas meja, memblokir pengguna lain. Jika Anda menggunakan aplikasi yang secara transparan mengirimkan pernyataan SQL ke server, aplikasi harus mengambil semua baris hasil. Jika tidak (dan jika tidak dapat dikonfigurasi untuk melakukannya), Anda mungkin tidak dapat menyelesaikan masalah pemblokiran. Untuk menghindari masalah, Anda dapat membatasi aplikasi yang berperilaku buruk ke pelaporan atau basis data pendukung keputusan. ' Terlebih lagi saya berbicara secara umum. Anda dapat membaca dari sini support2.microsoft.com/kb/224453
Shanky
4
@Shanky Buat tabel besar. SELECT *dari dalam di READ COMMITTEDdalam satu koneksi SSMS, monitor mengunci dari yang lain. Kapan saja, berapa banyak kunci yang Anda lihat dipegang?
Mark Storey-Smith