Sch-M WAIT bloquea Sch-S en SQL Server 2014 pero no SQL Server 2008 R2?


11

Recientemente migramos nuestras instancias de producción de SQL 2008 R2 a nuevos servidores SQL 2014. Aquí hay un escenario interesante que descubrimos con nuestro uso de Service Broker. Considere una base de datos Broker Enabled = truecon MyServicey MyQueue. El manejo de mensajes de veneno está deshabilitado en esta cola. Hay al menos 2 conversaciones activas con mensajes en la cola.

En un proceso (SPID 100) ejecute:

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

Tenga en cuenta que dejamos abierta la transacción. Imagine que es un programa .NET que espera mucho tiempo en algún recurso externo. A través de sys.dm_tran_locksvemos que este SPID ha recibido un bloqueo IX en la cola.

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

En un proceso separado (SPID 101) ejecute cinco veces :

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

La clave aquí es que estamos retrasando la transacción cinco veces . Esto activa la lógica de fondo integrada de Manejo de mensajes de envenenamiento . Si bien la cola no se deshabilita (porque está configurada para no deshabilitar), una tarea en segundo plano todavía está tratando de funcionar y disparar un broker_queue_disabledevento. Entonces, si volvemos a consultar sys.dm_tran_locks, veremos un SPID diferente (asociado con BRKR TASK) esperando en un bloqueo Sch-M.

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

Hasta ahora, todo tiene sentido.

Finalmente, en un proceso diferente (SPID 102), intente ENVIAR a un Servicio usando esa Cola:

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

El SENDcomando está bloqueado. Si volvemos a mirar sys.dm_tran_locks, vemos que este proceso está esperando un bloqueo Sch-S. Al ejecutar sp_who2, encontramos que SPID 102 está bloqueado por 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  |

¿Por qué una cerradura Sch-S espera en una cerradura Sch-M que también está esperando?

¡Este comportamiento es completamente diferente en SQL 2008 R2! Usando exactamente el mismo escenario, ejecutándose en nuestras instancias 2008R2 aún por desmantelar, el lote final que incluye el SENDcomando no se bloquea por el bloqueo Sch-M en espera.

¿Ha cambiado el comportamiento de bloqueo en SQL 2012 o 2014? ¿Existe alguna configuración de base de datos o servidor que pueda afectar este comportamiento de bloqueo?


Suena como un posible error. ¿Ha aplicado los últimos SP y CU?
Max Vernon

1
@MaxVernon estamos corriendo 12.00.2370
Joseph Daigle

3
Estás utilizando el mismo servicio como iniciador y objetivo. Los SENDbloques mientras se verifica la cola del iniciador . SENDno se bloquearía en la cola de destino , simplemente rebotaría y se usaría sys.transmission_queuepara la entrega. Si separa los dos (siempre es una buena idea) no tendría el problema.
Remus Rusanu

1
Gracias @RemusRusanu. Si bien este ejemplo está parcialmente diseñado para demostrar el comportamiento modificado, su consejo es uno que tendremos en cuenta al diseñar nuestros servicios y colas.
Joseph Daigle

Respuestas:


17

El comportamiento cambió entre SQL Server 2008 R2 y SQL Server 2012. La implementación de 2008 R2 fue inconsistente con la semántica documentada 'FIFO relajada' :

Los bloqueos se otorgan de manera relajada, primero en entrar, primero en salir (FIFO). Aunque el orden no es estrictamente FIFO, conserva las propiedades deseables, como evitar el hambre y trabaja para reducir los bloqueos y puntos muertos innecesarios.

Las nuevas solicitudes de bloqueo donde el solicitante aún no posee un bloqueo en el recurso se bloquean si el modo solicitado es incompatible con la unión de las solicitudes otorgadas y los modos de las solicitudes pendientes.

Una solicitud de conversión se bloquea solo si el modo solicitado es incompatible con la unión de todos los modos otorgados, excluyendo el modo en que se otorgó originalmente la solicitud de conversión.

En 2008 R2, Sch-Sse otorgó una nueva solicitud de bloqueo a pesar de ser incompatible con la unión de solicitudes otorgadas y en espera, lo que podría conducir a la inanición por bloqueo. En 2012, la Sch-Ssolicitud de bloqueo está bloqueada.

El siguiente script de reproducción utiliza tablas regulares en lugar de una cola de 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 resumen, 2008 R2 no se comportó como se diseñó. El problema se solucionó en SQL Server 2012.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.