Nous avons récemment migré nos instances de production de SQL 2008 R2 à de nouveaux serveurs SQL 2014. Voici un scénario intéressant que nous avons découvert avec notre utilisation du courtier de service. Considérez une base de données avec Broker Enabled = true
avec MyService
et MyQueue
. La manipulation des messages antipoison est désactivée sur 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 certaines ressources externes. Passant par sys.dm_tran_locks
Nous voyons que cette spid a été accordée à une serrure IX sur la file d'attente.
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
Dans un processus séparé (SPID 101) Exécuter 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 renvoyons la transaction cinq fois. Cela déclenche la logique de fond intégrée Traitement des messages antipoison . Bien que la file d'attente ne soit pas désactivée (car elle est configurée pour ne pas désactiver), une tâche d'arrière-plan essaie toujours de faire du travail et de tirer un broker_queue_disabled
un événement. Alors maintenant, si nous interrogeons sys.dm_tran_locks
Encore une fois, nous verrons une spid différente (associée à BRKR TASK
) En attente d'une serrure 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), tenter d'envoyer à un service à l'aide de 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 commande SEND
est bloquée. Si on regarde à nouveau sys.dm_tran_locks
Nous voyons que ce processus attend sur une serrure Sch-S. Exécuter sp_who2
Nous trouvons que SPID 102 est bloqué par 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 une serrure Sch-s attendra-t-elle un verrou Sch-M qui attend également?
Ce comportement est complètement différent dans SQL 2008 R2! Utilisation de ce même scénario, en cours d'exécution sur nos instances de 2008R2 non décomptables, le lot final comprenant la commande SEND
ne le fait pas Être bloqué par l'attente SCH-M serrure.
Le comportement de verrouillage a-t-il changé dans SQL 2012 ou 2014? Y a-t-il peut-être une base de données ou un paramètre de serveur qui pourrait affecter ce comportement de verrouillage?
Le comportement a changé entre SQL Server 2008 R2 et SQL Server 2012. La mise en œuvre de 2008 R2 était incompatible avec la sémantique documentée "FIFO FIFO" :
Les serrures sont octroyées dans une mode de première entrée, de premier an (FIFO) relâchée (FIFO). Bien que la commande ne soit pas stricte FIFO, elle conserve des propriétés souhaitables, telles que l'évité de la famine et des œuvres afin de réduire les blocages et le blocage inutiles.
Nouvelles demandes de verrouillage Si le demandeur ne possède pas encore de verrouillage de la ressource est bloqué si le mode demandé est incompatible avec l'Union des demandes accordées et les modes de demandes en attente.
[.____] Une demande de conversion ne devient 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 était octroyée.
En 2008 R2, une nouvelle Sch-S
La demande de verrouillage a été accordée malgré elle d'être incompatible avec l'Union des demandes d'acquisition et d'attente, ce qui pourrait conduire à la fermeture de la fermeture. En 2012, le Sch-S
La demande de verrouillage est bloquée.
Le script de reproduction ci-dessous utilise des tables régulières plutôt qu'une file d'attente de courtiers de service:
-- 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 se comportait pas comme conçu. Le problème a été corrigé dans SQL Server 2012.