Extendiendo la respuesta de Mark ...
Cuando se produce un evento de tiempo de espera del cliente (.net CommandTimeout, por ejemplo), el cliente envía un "ABORTAR" a SQL Server. SQL Server simplemente abandona el procesamiento de la consulta. No se revierte ninguna transacción, no se liberan bloqueos.
Ahora, la conexión se devuelve al grupo de conexiones, por lo que no está cerrada en SQL Server. Si esto sucede alguna vez (a través de KILL o reinicio del cliente, etc.), las transacciones + bloqueos se borrarán. Tenga en cuenta que sp_reset_connection no los borrará o no, a pesar de que se anuncia que lo hará
Este detrito del aborto bloqueará otros procesos.
La forma de hacer que SQL Server borre transacciones + bloqueos en el tiempo de espera del cliente (estrictamente, eventos ABORT) es usar SET XACT_ABORT ON.
Puede verificar que esto esté abriendo 2 ventanas de consulta en SSMS:
Ventana 1:
En el menú Consulta ... Opciones de consulta establezca un tiempo de espera de 5 segundos y luego ejecute esto
BEGIN TRAN
UPDATE sometable WITH (TABLOCKX) SET foo = foo WHERE 1 = 0;
WAITFOR DELAY '00:00:10' -- just has to be longer then timeout
Ventana 2, esto esperará para siempre (o llegará a su tiempo de espera)
SELECT * FROM sometable
SET XACT_ABORT ON también tiene interesantes efectos secundarios:
- @@ TRANCOUNT se establece en cero en la reversión implícita pero se suprime el error 266 (esto sucede si @@ TRANCOUNT es diferente al entrar y salir de un proceso almacenado)
- XACT_STATE será -1 (está "condenado")
La combinación de esto significa que no puede usar SAVEPOINTS (aunque no recuerdo el comportamiento exacto) para confirmaciones / retrocesos parciales. Que me conviene
Enlaces SO en SET XACT_ABORT:
En procesos almacenados anidados:
En sp_reset_connection:
Estoy respondiendo esto con dudas ya que no hay suficiente información en su descripción del problema para estar 100% seguro de que este es el mejor consejo. "Cuelga o lanza una excepción" sugiere que la fuente del problema no se entiende correctamente, así que proceda con precaución.
La solución más simple para esto es probablemente
SET XACT_ABORT ON
.XACT_ABORT
determina si SQL Server revertirá una transacción en caso de un error en tiempo de ejecución. El valor predeterminadoSET XACT_ABORT OFF
revertirá solo la declaración que causó un error, dejando abierta cualquier transacción principal.El "efecto secundario" de la configuración predeterminada es que un tiempo de espera puede causar exactamente el mismo problema, una transacción abierta que es responsabilidad del cliente manejar y revertir. Si el cliente no intenta / atrapar / revertir, la transacción permanecerá abierta hasta que se atienda (y cito @gbn) la ultraviolencia de
KILL <spid>
.Los artículos de Erland Sommarskog citados a menudo sobre el manejo de errores en SQL Server contienen todos los antecedentes y la estrategia que necesita para lidiar con estos escenarios y más.
Editar (siguiente comentario): para identificar transacciones abiertas, sp_whoisactive es probablemente la característica más completa.
fuente