Sch-M WAIT blocca Sch-S in SQL Server 2014 ma non in SQL Server 2008 R2?


11

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?


Sembra un possibile bug. Hai applicato gli ultimi SP e CU?
Max Vernon,

1
@MaxVernon stiamo correndo il 12.00.2370
Joseph Daigle il

3
Stai utilizzando lo stesso servizio di iniziatore e destinazione. I 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.
Remus Rusanu,

1
Grazie @RemusRusanu. Mentre questo esempio è parzialmente concepito per dimostrare il comportamento modificato, il tuo suggerimento è uno che terremo presente quando progettiamo i nostri servizi e le nostre code.
Joseph Daigle,

Risposte:


17

Il comportamento è cambiato tra SQL Server 2008 R2 e SQL Server 2012. L'implementazione di 2008 R2 non era coerente con la semantica "rilassata FIFO" documentata :

Le serrature sono concesse in modo rilassato, first-in, first-out (FIFO). Sebbene l'ordine non sia rigoroso FIFO, conserva proprietà desiderabili come evitare la fame e lavora per ridurre inutili deadlock e blocchi.

Le nuove richieste di blocco in cui il richiedente non possiede ancora un blocco sulla risorsa vengono bloccate se la modalità richiesta è incompatibile con l'unione di richieste concesse e le modalità di richieste in sospeso.

Una richiesta di conversione viene bloccata solo se la modalità richiesta è incompatibile con l'unione di tutte le modalità concesse, esclusa la modalità in cui la richiesta di conversione stessa è stata inizialmente concessa.

Nel 2008 R2, una nuova Sch-Srichiesta di blocco è stata concessa nonostante fosse incompatibile con l'unione di richieste concesse e in attesa, il che potrebbe portare alla fame di blocco. Nel 2012, la Sch-Srichiesta di blocco è bloccata.

Lo script di riproduzione di seguito utilizza tabelle regolari anziché una coda di Service Broker:

-- Session 1
CREATE TABLE dbo.LockTest (col1 integer NULL);

INSERT dbo.LockTest (col1) VALUES (1);

BEGIN TRANSACTION;

-- Will hold row-X, Pag-IX, and Tab-IX
INSERT dbo.LockTest (col1) VALUES (2);

-- Session 2
-- Blocked waiting on Sch-M
TRUNCATE TABLE dbo.LockTest;

-- Session 3
-- Takes Sch-S only
-- Not blocked in 2008 R2
SELECT * FROM dbo.LockTest AS LT WITH (READUNCOMMITTED);

In sintesi, 2008 R2 non si è comportato come previsto. Il problema è stato risolto in SQL Server 2012.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.