Sch-M WAIT blockiert Sch-S in SQL Server 2014, aber nicht SQL Server 2008 R2?

11

Wir haben kürzlich unsere Produktionsinstanzen von SQL 2008 R2 auf brandneue SQL 2014-Server migriert. Hier ist ein interessantes Szenario, das wir bei der Verwendung von Service Broker entdeckt haben. Betrachten Sie eine Datenbank Broker Enabled = truemit MyServiceund MyQueue. Die Behandlung von Giftnachrichten ist in dieser Warteschlange deaktiviert. Es gibt mindestens 2 aktive Konversationen mit Nachrichten in der Warteschlange.

In einem Prozess (SPID 100) ausführen:

BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;

Beachten Sie, dass wir die Transaktion offen lassen. Stellen Sie sich vor, es ist ein .NET-Programm, das lange auf eine externe Ressource wartet. Über sehen sys.dm_tran_lockswir, dass dieser SPID eine IX-Sperre für die Warteschlange gewährt wurde.

| type   | resource_id | mode | status | spid |
| OBJECT | 277576027   | IX   | GRANT  | 100  |

In einem separaten Prozess (SPID 101) fünfmal ausführen :

BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;
ROLLBACK TRANSACTION;

Der Schlüssel hier ist, dass wir die Transaktion fünfmal zurücksetzen . Dies löst die integrierte Hintergrundlogik für die Behandlung von Giftnachrichten aus. Während die Warteschlange nicht deaktiviert wird (weil sie so konfiguriert ist, dass sie nicht deaktiviert wird), versucht eine Hintergrundaufgabe immer noch, Arbeit zu leisten und ein broker_queue_disabledEreignis auszulösen. Wenn wir jetzt sys.dm_tran_lockserneut abfragen , sehen wir eine andere SPID (verbunden mit BRKR TASK), die auf eine Sch-M-Sperre wartet.

| type   | resource_id | mode  | status | spid |
| OBJECT | 277576027   | IX    | GRANT  | 100  |
| OBJECT | 277576027   | Sch-M | WAIT   | 36   |

Bisher macht alles Sinn.

Versuchen Sie schließlich bei einem anderen Prozess (SPID 102), mithilfe dieser Warteschlange an einen Dienst zu senden:

BEGIN TRANSACTION;
DECLARE @ch uniqueidentifier;
BEGIN DIALOG @ch FROM SERVICE [MyService] TO SERVICE 'MyService';
SEND ON CONVERSATION @ch ('HELLO WORLD');

Der SENDBefehl ist blockiert. Wenn wir uns das noch einmal sys.dm_tran_locksansehen, sehen wir, dass dieser Prozess auf ein Sch-S-Schloss wartet. Bei der Ausführung stellen sp_who2wir fest, dass SPID 102 durch SPID 36 blockiert ist.

| type   | resource_id | mode  | status | spid |
| OBJECT | 277576027   | IX    | GRANT  | 100  |
| OBJECT | 277576027   | Sch-M | WAIT   | 36   |
| OBJECT | 277576027   | Sch-S | WAIT   | 102  |

Warum wartet eine Sch-S-Sperre auf eine Sch-M-Sperre, die ebenfalls wartet?

Dieses Verhalten ist in SQL 2008 R2 völlig anders! Unter Verwendung des gleichen Szenarios, das auf unseren noch nicht stillgelegten 2008R2-Instanzen ausgeführt wird, wird der letzte Stapel einschließlich des SENDBefehls nicht durch die wartende Sch-M-Sperre blockiert.

Hat sich das Sperrverhalten in SQL 2012 oder 2014 geändert? Gibt es möglicherweise eine Datenbank- oder Servereinstellung, die dieses Sperrverhalten beeinflussen könnte?

Joseph Daigle
quelle
Klingt nach einem möglichen Fehler. Haben Sie die neuesten SP und CUs angewendet?
Max Vernon
1
@ MaxVernon wir laufen 12.00.2370
Joseph Daigle
3
Sie verwenden denselben Dienst wie Initiator und Ziel. Die SENDBlöcke beim Überprüfen der Initiatorwarteschlange . SENDwürde nicht auf der Block Zielwarteschlange, wäre es einfach abprallen und Verwendung sys.transmission_queuefür die Lieferung. Wenn Sie die beiden trennen (immer eine gute Idee), hätten Sie das Problem nicht.
Remus Rusanu
1
Danke @RemusRusanu. Während dieses Beispiel teilweise dazu dient, das geänderte Verhalten zu demonstrieren, ist Ihr Tipp einer, den wir beim Entwerfen unserer Dienste und Warteschlangen berücksichtigen werden.
Joseph Daigle

Antworten:

17

Das Verhalten hat sich zwischen SQL Server 2008 R2 und SQL Server 2012 geändert. Die Implementierung von 2008 R2 stimmte nicht mit der überein dokumentierten "entspannten FIFO" -Semantik überein :

Sperren werden entspannt nach dem FIFO-Prinzip (First-In, First-Out) gewährt. Obwohl die Reihenfolge nicht streng FIFO ist, werden wünschenswerte Eigenschaften wie die Vermeidung von Hunger beibehalten und unnötige Deadlocks und Blockierungen reduziert.

Neue Sperranforderungen, bei denen der Anforderer noch keine Sperre für die Ressource besitzt, werden blockiert, wenn der angeforderte Modus nicht mit der Vereinigung gewährter Anforderungen und den Modi ausstehender Anforderungen kompatibel ist.

Eine Konvertierungsanforderung wird nur blockiert, wenn der angeforderte Modus nicht mit der Vereinigung aller gewährten Modi kompatibel ist, mit Ausnahme des Modus, in dem die Konvertierungsanforderung selbst ursprünglich gewährt wurde.

Im Jahr 2008 R2 eine neue Sch-S Sperranforderung gewährt, obwohl diese nicht mit der Vereinigung von erteilten und wartenden Anforderungen kompatibel ist, was zu einem Hungersnot führen kann. Im Jahr 2012 wird die Sch-SSperranforderung blockiert.

Das folgende Reproduktionsskript verwendet reguläre Tabellen anstelle einer Service Broker-Warteschlange:

-- 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);

Zusammenfassend hat sich 2008 R2 nicht wie geplant verhalten. Das Problem wurde in SQL Server 2012 behoben.

Paul White 9
quelle