Recentemente, migramos nossas instâncias de produção do SQL 2008 R2 para novos servidores SQL 2014. Aqui está um cenário interessante que descobrimos com o uso do Service Broker. Considere um banco de dados Broker Enabled = true
com MyService
e MyQueue
. O tratamento de mensagens suspeitas está desabilitado nesta fila. Existem pelo menos 2 conversas ativas com mensagens na fila.
Em um processo (SPID 100), execute:
BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;
Observe que deixamos a transação aberta. Imagine que é um programa .NET que está aguardando muito tempo em algum recurso externo. Via sys.dm_tran_locks
vemos que esse SPID recebeu um bloqueio IX na fila.
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
Em um processo separado (SPID 101), execute cinco vezes :
BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;
ROLLBACK TRANSACTION;
A chave aqui é que estamos revertendo a transação cinco vezes . Isso aciona a lógica de fundo de manipulação de mensagens de veneno incorporada . Embora a fila não seja desabilitada (porque está configurada para não desabilitar), uma tarefa em segundo plano ainda está tentando executar o trabalho e disparar um broker_queue_disabled
evento. Então, agora, se consultarmos sys.dm_tran_locks
novamente, veremos um SPID diferente (associado a BRKR TASK
) aguardando um bloqueio Sch-M.
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
| OBJECT | 277576027 | Sch-M | WAIT | 36 |
Até agora, tudo faz sentido.
Finalmente, em um processo diferente (SPID 102), tente ENVIAR para um serviço usando essa fila:
BEGIN TRANSACTION;
DECLARE @ch uniqueidentifier;
BEGIN DIALOG @ch FROM SERVICE [MyService] TO SERVICE 'MyService';
SEND ON CONVERSATION @ch ('HELLO WORLD');
O SEND
comando está bloqueado. Se olharmos novamente sys.dm_tran_locks
, vemos que esse processo está aguardando um bloqueio Sch-S. Ao executar sp_who2
, descobrimos que o SPID 102 está bloqueado pelo 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 que um bloqueio Sch-S aguarda um bloqueio Sch-M que também está aguardando?
Esse comportamento é completamente diferente no SQL 2008 R2! Usando exatamente esse mesmo cenário, executando em nossas instâncias 2008R2 ainda a serem descomissionadas, o lote final, incluindo o SEND
comando , não é bloqueado pelo bloqueio Sch-M em espera.
O comportamento do bloqueio foi alterado no SQL 2012 ou 2014? Existe talvez alguma configuração de banco de dados ou servidor que possa afetar esse comportamento de bloqueio?
fonte
SEND
blocos enquanto verifica a fila do iniciador .SEND
não bloquearia na fila de destino , simplesmente retornaria e seria usadasys.transmission_queue
para entrega. Se você separar os dois (sempre uma boa ideia), não terá o problema.Respostas:
O comportamento mudou entre o SQL Server 2008 R2 e o SQL Server 2012. A implementação do 2008 R2 era inconsistente com a semântica documentada 'FIFO relaxado' :
Em 2008 R2, uma nova
Sch-S
solicitação de bloqueio foi concedida, apesar de incompatível com a união de solicitações concedidas e em espera, o que pode levar à privação de bloqueio. Em 2012, aSch-S
solicitação de bloqueio é bloqueada.O script de reprodução abaixo usa tabelas regulares em vez de uma fila do Service Broker:
Em resumo, o 2008 R2 não se comportou como projetado. O problema foi corrigido no SQL Server 2012.
fonte