Kami baru-baru ini memigrasi instance produksi kami dari SQL 2008 R2 ke server SQL 2014 baru. Berikut adalah skenario menarik yang kami temukan dengan penggunaan Broker Layanan kami. Pertimbangkan basis data Broker Enabled = true
dengan MyService
dan MyQueue
. Penanganan pesan racun dinonaktifkan pada antrian ini. Setidaknya ada 2 percakapan aktif dengan pesan dalam antrian.
Dalam satu proses (SPID 100) jalankan:
BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;
Perhatikan bahwa kami membiarkan transaksi terbuka. Bayangkan itu adalah program .NET yang menunggu lama pada beberapa sumber daya eksternal. Melalui sys.dm_tran_locks
kita melihat bahwa SPID ini telah diberikan kunci IX pada antrian.
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
Dalam proses terpisah (SPID 101) jalankan lima kali :
BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;
ROLLBACK TRANSACTION;
Kuncinya di sini adalah bahwa kita memutar kembali transaksi lima kali . Ini memicu logika latar belakang Penanganan Pesan Racun bawaan . Sementara antrian tidak dinonaktifkan (karena dikonfigurasi untuk tidak menonaktifkan), tugas latar belakang masih mencoba melakukan pekerjaan dan menjalankan suatu broker_queue_disabled
acara. Jadi sekarang jika kita query sys.dm_tran_locks
lagi kita akan melihat SPID berbeda (terkait dengan BRKR TASK
) menunggu kunci Sch-M.
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
| OBJECT | 277576027 | Sch-M | WAIT | 36 |
Sejauh ini, semuanya masuk akal.
Akhirnya, pada proses yang berbeda (SPID 102), cobalah untuk MENGIRIM ke Layanan menggunakan Antrian itu:
BEGIN TRANSACTION;
DECLARE @ch uniqueidentifier;
BEGIN DIALOG @ch FROM SERVICE [MyService] TO SERVICE 'MyService';
SEND ON CONVERSATION @ch ('HELLO WORLD');
The SEND
perintah diblokir. Jika kita melihat lagi pada sys.dm_tran_locks
kita melihat bahwa proses ini menunggu pada kunci Sch-S. Melaksanakan sp_who2
kami menemukan bahwa SPID 102 diblokir oleh SPID 36.
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
| OBJECT | 277576027 | Sch-M | WAIT | 36 |
| OBJECT | 277576027 | Sch-S | WAIT | 102 |
Mengapa kunci Sch-S menunggu pada kunci Sch-M yang juga menunggu?
Perilaku ini sangat berbeda dalam SQL 2008 R2! Menggunakan skenario yang sama persis ini, berjalan pada contoh 2008R2 kami yang belum dinonaktifkan, batch terakhir termasuk SEND
perintah tidak akan diblokir oleh kunci Sch-M yang menunggu.
Apakah perilaku penguncian berubah di SQL 2012 atau 2014? Apakah mungkin ada beberapa pengaturan database atau server yang dapat mempengaruhi perilaku penguncian ini?
sumber
SEND
blok sambil memeriksa inisiator antrian.SEND
tidak akan memblokir antrian target , itu hanya akan terpental dan digunakansys.transmission_queue
untuk pengiriman. Jika Anda memisahkan keduanya (selalu merupakan ide bagus), Anda tidak akan memiliki masalah.Jawaban:
Perilaku memang berubah antara SQL Server 2008 R2 dan SQL Server 2012. Implementasi 2008 R2 tidak konsisten dengan semantik 'santai FIFO' yang didokumentasikan :
Pada 2008 R2,
Sch-S
permintaan kunci baru dikabulkan meskipun tidak sesuai dengan penyatuan permintaan yang dikabulkan dan menunggu, yang dapat menyebabkan kelaparan kunci. Pada 2012,Sch-S
permintaan kunci diblokir.Skrip reproduksi di bawah ini menggunakan tabel biasa daripada antrian Pialang Layanan:
Singkatnya, 2008 R2 tidak berperilaku seperti yang dirancang. Masalahnya diperbaiki pada SQL Server 2012.
sumber