Tiempo de espera de transacción de SQL Server

9

¿Hay alguna manera en SQL Server 2008 R2 de causar un tiempo de espera para una modificación de la base de datos que involucra una transacción? Tenemos un escenario en el que nuestro código de aplicación se cuelga o genera una excepción y no puede realizar una reversión o confirmación. Esto hace que otras sesiones se cuelguen esperando que se complete la transacción.

David Gray Wright
fuente

Respuestas:

20

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:

gbn
fuente
El futuro dice hola! "Tenga en cuenta que sp_reset_connection no los borrará o no los borrará, a pesar de que se anuncia que lo haga". ¿No creo que esto sea cierto en las versiones actualizadas de SQL Server?
kamilk
11

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_ABORTdetermina si SQL Server revertirá una transacción en caso de un error en tiempo de ejecución. El valor predeterminado SET XACT_ABORT OFFrevertirá 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.

Mark Storey-Smith
fuente
Encontré, con algunos Google, formas de encontrar transacciones abiertas cuando ocurre el bloqueo, tal vez esta es la mejor solución. Eso es para encontrar la causa de la transacción no cerrada en el código y corregir los agujeros en el código. Para referencia para otros. DBCC OPENTRAN devuelve la transacción activa más antigua -> msdn.microsoft.com/en-us/library/ms182792.aspx ¿ O algo más como esto? -> weblogs.sqlteam.com/mladenp/archive/2008/04/29/…
David Gray Wright
Siempre pensé que Erland no le hizo justicia al SET XACT_ABORT sommarskog.se/error-handling-I.html#XACT_ABORT
gbn