Sch-M WAIT bloque Sch-S dans SQL Server 2014 mais pas SQL Server 2008 R2?

11

Nous avons récemment migré nos instances de production de SQL 2008 R2 vers de nouveaux serveurs SQL 2014. Voici un scénario intéressant que nous avons découvert avec notre utilisation de Service Broker. Considérez une base de données avec Broker Enabled = trueavec MyServiceet MyQueue. La gestion des messages incohérents est désactivée dans cette file d'attente. Il y a au moins 2 conversations actives avec des messages dans la file d'attente.

Dans un processus (SPID 100), exécutez:

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

Notez que nous laissons la transaction ouverte. Imaginez que c'est un programme .NET qui attend longtemps sur une ressource externe. Via, sys.dm_tran_locksnous voyons que ce SPID a obtenu un verrou IX sur la file d'attente.

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

Dans un processus distinct (SPID 101), exécutez cinq fois :

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

La clé ici est que nous annulons la transaction cinq fois . Cela déclenche la logique d'arrière-plan de gestion des messages antipoison intégrée . Bien que la file d'attente ne soit pas désactivée (car elle est configurée pour ne pas se désactiver), une tâche en arrière-plan essaie toujours de fonctionner et de déclencher un broker_queue_disabledévénement. Alors maintenant, si nous interrogeons à sys.dm_tran_locksnouveau, nous verrons un SPID différent (associé à BRKR TASK) en attente sur un verrou Sch-M.

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

Jusqu'à présent, tout a du sens.

Enfin, sur un processus différent (SPID 102), essayez d'envoyer à un service en utilisant cette file d'attente:

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

La SENDcommande est bloquée. Si nous regardons à nouveau, sys.dm_tran_locksnous voyons que ce processus attend sur un verrou Sch-S. En cours d'exécution, sp_who2nous constatons que le SPID 102 est bloqué par le 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  |

Pourquoi un verrou Sch-S attend-il sur un verrou Sch-M qui attend également?

Ce comportement est complètement différent dans SQL 2008 R2! En utilisant exactement ce même scénario, exécuté sur nos instances 2008R2 non encore mises hors service, le lot final comprenant la SENDcommande n'est pas bloqué par le verrou Sch-M en attente.

Le comportement de verrouillage a-t-il changé dans SQL 2012 ou 2014? Y a-t-il peut-être un paramètre de base de données ou de serveur qui pourrait affecter ce comportement de verrouillage?

Joseph Daigle
la source
Cela ressemble à un bug possible. Avez-vous appliqué les derniers SP et CU?
Max Vernon
1
@MaxVernon nous courons 12.00.2370
Joseph Daigle
3
Vous utilisez le même service que l'initiateur et la cible. Les SENDblocs lors de la vérification de la file d'attente de l' initiateur . SENDne bloquerait pas la file d'attente cible , il rebondirait simplement et serait utilisé sys.transmission_queuepour la livraison. Si vous séparez les deux (toujours une bonne idée), vous n'auriez pas le problème.
Remus Rusanu
1
Merci @RemusRusanu. Bien que cet exemple soit partiellement conçu pour illustrer le changement de comportement, votre conseil est celui que nous garderons à l'esprit lors de la conception de nos services et de nos files d'attente.
Joseph Daigle

Réponses:

17

Le comportement a changé entre SQL Server 2008 R2 et SQL Server 2012. L'implémentation de 2008 R2 n'était pas cohérente avec la sémantique documentée «FIFO détendue» :

Les verrous sont accordés de manière décontractée premier entré, premier sorti (FIFO). Bien que la commande ne soit pas strictement FIFO, elle préserve les propriétés souhaitables telles que d'éviter la famine et travaille à réduire les blocages inutiles et le blocage.

Les nouvelles demandes de verrouillage où le demandeur ne possède pas encore de verrou sur la ressource sont bloquées si le mode demandé est incompatible avec l'union des demandes accordées et les modes des demandes en attente.

Une demande de conversion n'est bloquée que si le mode demandé est incompatible avec l'union de tous les modes accordés, à l'exclusion du mode dans lequel la demande de conversion elle-même a été initialement accordée.

En 2008 R2, une nouvelle Sch-Sdemande de verrouillage a été accordée bien qu'elle soit incompatible avec l'union des demandes accordées et en attente, ce qui pourrait conduire à la famine de verrouillage. En 2012, la Sch-Sdemande de verrouillage est bloquée.

Le script de reproduction ci-dessous utilise des tables régulières plutôt qu'une file d'attente 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);

En résumé, 2008 R2 ne s'est pas comporté comme prévu. Le problème a été résolu dans SQL Server 2012.

Paul White 9
la source