Di recente abbiamo migrato le nostre istanze di produzione da SQL 2008 R2 a nuovissimi server SQL 2014. Ecco uno scenario interessante che abbiamo scoperto con il nostro utilizzo di Service Broker. Considerare un database con Broker Enabled = truecon MyServicee MyQueue. La gestione dei messaggi velenosi è disabilitata su questa coda. Ci sono almeno 2 conversazioni attive con messaggi nella coda.
In un processo (SPID 100) eseguire:
BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;
Si noti che lasciamo aperta la transazione. Immagina che si tratti di un programma .NET in attesa da tempo su alcune risorse esterne. Tramite sys.dm_tran_locksvediamo che a questo SPID è stato concesso un blocco IX sulla coda.
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
In un processo separato (SPID 101) eseguire cinque volte :
BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;
ROLLBACK TRANSACTION;
La chiave qui è che stiamo eseguendo il rollback della transazione cinque volte . Ciò innesca la logica di background di gestione dei messaggi Poison integrata . Mentre la coda non viene disabilitata (perché è configurata per non disabilitarsi), un'attività in background sta ancora tentando di funzionare e generare un broker_queue_disabledevento. Quindi ora se eseguiamo sys.dm_tran_locksnuovamente una query vedremo un SPID diverso (associato BRKR TASK) in attesa su un blocco Sch-M.
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
| OBJECT | 277576027 | Sch-M | WAIT | 36 |
Finora tutto ha un senso.
Infine, su un altro processo (SPID 102), prova a INVIARE a un servizio utilizzando quella coda:
BEGIN TRANSACTION;
DECLARE @ch uniqueidentifier;
BEGIN DIALOG @ch FROM SERVICE [MyService] TO SERVICE 'MyService';
SEND ON CONVERSATION @ch ('HELLO WORLD');
Il SENDcomando è bloccato Se guardiamo di nuovo sys.dm_tran_locksvediamo che questo processo è in attesa di un blocco Sch-S. In esecuzione sp_who2troviamo che SPID 102 è bloccato da 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 |
Perché un lucchetto Sch-S attende un lucchetto Sch-M che sta aspettando?
Questo comportamento è completamente diverso in SQL 2008 R2! Utilizzando questo stesso identico scenario, in esecuzione sulle nostre istanze 2008R2 ancora da mettere fuori servizio, il batch finale incluso il SENDcomando non viene bloccato dal blocco Sch-M in attesa.
Il comportamento di blocco è cambiato in SQL 2012 o 2014? C'è forse qualche impostazione di database o server che potrebbe influenzare questo comportamento di blocco?
SENDblocchi durante il controllo della coda dell'iniziatore . SENDnon si bloccherebbe sulla coda di destinazione , rimbalzerebbe e userebbe semplicemente sys.transmission_queueper la consegna. Se separi i due (sempre una buona idea) non avresti il problema.