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: