Alguém já ouviu falar em transações distribuídas órfãs no SQL Server? Oficialmente são transações do MSDTC não associadas a um ID real, mas alguns apelidaram carinhosamente como “transações fantasmas”. Geralmente esses processos se resolvem por si só, ou seja, entram e saem do banco sem afetar nada. Porém, em algumas situações podem prejudicar seu ambiente, gerando alguns inconvenientes.

Você pode identificar facilmente estas transações, pois a partir da versão 2000 do SQL Server, elas são associadas automaticamente ao SPID -2. É possível encontrar algumas documentações da Microsoft sobre este assunto.

Particularmente, já compartilhei de algumas experiências com transações órfãs. Em uma situação, uma conexão fantasma bloqueou o reindex full do banco de produção, impactando a disponibilidade da aplicação.

Nestas situações, a única forma de resolver é derrubar a transação órfã, através de um KILL. Sabendo que não é possível matar um processo -2 (negativo), você pode recorrer ao seguinte script, dividido em dois passos:

1 – Listar os ids internos das transações. Sempre que for diferente de '00000000-0000-0000-0000-000000000000', é uma transação órfã:

SELECT DISTINCT req_transactionUOW FROM syslockinfo WHERE req_transactionuow <> '00000000-0000-0000-0000-000000000000'

2 – Copiar o(s) id(s) e executar o comando KILL:

KILL '00000000-0000-0000-0000-000000000000'

Se isto for muito constante no seu ambiente, você pode agendar um Job que verifica a existência dessas transações, e derrubar automaticamente. Segue uma procedure para ajudar você nesta tarefa:

CREATE PROCEDURE USP_KILL_TRANSACTION_UOW

AS

DECLARE @qtd INT

SELECT @qtd = count(*) FROM syslockinfo WHERE req_transactionuow <> '00000000-0000-0000-0000-000000000000'

IF @qtd > 0

BEGIN

      DECLARE @uspid VARCHAR(255)

      DECLARE csr_TUOW CURSOR FOR

      SELECT DISTINCT req_transactionUOW FROM syslockinfo WHERE req_transactionuow <> '00000000-0000-0000-0000-000000000000'

      OPEN csr_TUOW

     

            FETCH NEXT FROM csr_TUOW INTO @uspid

           

            WHILE @@FETCH_STATUS = 0

            BEGIN                  

                  EXEC('KILL ''' + @uspid + '''')

                  FETCH NEXT FROM csr_TUOW INTO @uspid           

            END

      CLOSE csr_TUOW

      DEALLOCATE csr_TUOW

END

GO

 

Até a próxima!

Ivan Candido
ivandba@hotmail.com