2009-07-19 10 views

Respuesta

166

SET XACT_ABORT ON indica a SQL Server que revierte la transacción completa y anule el lote cuando se produce un error en tiempo de ejecución. Se le cubre en casos como un tiempo de espera de comandos que ocurren en la aplicación cliente en lugar de dentro de SQL Server en sí (que no está cubierta por la configuración predeterminada XACT_ABORT OFF.)

Desde un tiempo de espera de consulta saldrá de la transacción abierta, se recomienda SET XACT_ABORT ON en todos los procedimientos almacenados con transacciones explícitas (a menos que tenga una razón específica para hacer lo contrario) ya que las consecuencias de una aplicación que realiza el trabajo en una conexión con una transacción abierta son desastrosas.

Hay una muy buena visión general sobre Dan Guzman's Blog,

+8

¿por qué no está activado por defecto? –

1

Se utiliza en la gestión de transacciones para garantizar que los errores provoquen que la transacción se retrotraiga.

25

En mi opinión SET EN XACT_ABORT se hizo obsoleto por la adición de COMENZAR TRY/CATCH COMENZAR en 2k5 SQL. Antes de los bloques de excepción en Transact-SQL era muy difícil manejar los errores y los procedimientos desequilibrados eran demasiado comunes (procedimientos que tenían un @@ TRANCOUNT diferente en la salida en comparación con la entrada).

Con la adición del manejo de excepciones de Transact-SQL es mucho más fácil escribir procedimientos correctos que garanticen un equilibrio adecuado de las transacciones. Por ejemplo, yo uso este template for exception handling and nested transactions:

create procedure [usp_my_procedure_name] 
as 
begin 
    set nocount on; 
    declare @trancount int; 
    set @trancount = @@trancount; 
    begin try 
     if @trancount = 0 
      begin transaction 
     else 
      save transaction usp_my_procedure_name; 

     -- Do the actual work here 

lbexit: 
     if @trancount = 0 
      commit; 
    end try 
    begin catch 
     declare @error int, @message varchar(4000), @xstate int; 
     select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE(); 
     if @xstate = -1 
      rollback; 
     if @xstate = 1 and @trancount = 0 
      rollback 
     if @xstate = 1 and @trancount > 0 
      rollback transaction usp_my_procedure_name; 

     raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ; 
    end catch 
end 
go 

Me permite escribir procedimientos atómicos que sólo retrotracción su propio trabajo en caso de errores recuperables.

Uno de los principales problemas que enfrentan los procedimientos de Transact-SQL es la pureza de datos : a veces los parámetros recibidos o los datos de las tablas son simplemente errónea, lo que resulta en errores de clave duplicados, referencial limitan errores, comprobar limitar los errores y por lo tanto y así sucesivamente. Después de todo, esa es exactamente la función de estas restricciones, si estos errores de pureza de datos fueran imposibles y todos atrapados por la lógica comercial, las restricciones quedarían obsoletas (se agregará una exageración dramática para el efecto). Si XACT_ABORT está activado, todos estos errores provocan que se pierda toda la transacción, en lugar de poder codificar los bloques de excepciones que manejan la excepción correctamente. Un ejemplo típico es tratar de hacer un INSERTO y volver a una ACTUALIZACIÓN sobre la violación de PK.

+6

Excepto por los tiempos de espera de los clientes ... y mi opinión es que SET XACT_ABORT es más efectivo en SQL 2005 porque el comportamiento es más predecible: muchos menos errores de interrupción de lotes. – gbn

+2

* los tiempos de espera del cliente * son errores de la aplicación. Ninguna aplicación debería imponer un tiempo de espera de comando, nunca. Es una práctica terriblemente pobre que el tiempo de espera de SqlClient predeterminado me da un dolor de cabeza cada vez que pienso cómo podrían enviar algo así. Puede guiar todo el manejo de errores de Transact-SQL alrededor del problema de tiempo de espera, o puede codificar al cliente correctamente y solucionar los problemas de negocios en el manejo de errores. Por supuesto, mi punto de vista es desde el punto de vista de un desarrollador. los que están en el rol de administrador/dba generalmente ven el mundo de manera diferente, dado que están atrapados con las aplicaciones que otros crean. –

+6

Estoy de acuerdo, pero planeo mi manejo de errores en todas las eventualidades, porque sé que me echarán la culpa como Desarrollador DBA si se produce un tiempo de espera de comando. – gbn

19

Citando MSDN:

Cuando SET XACT_ABORT está en ON, si una instrucción de Transact-SQL genera un error en tiempo de ejecución, toda la transacción se termina y deshace. Cuando SET XACT_ABORT está desactivado, en algunos casos solo se retrotrae la instrucción de Transact-SQL que generó el error y la transacción continúa procesándose.

En la práctica esto significa que algunas de las declaraciones pueden fallar, dejando la transacción "parcialmente completada", y puede que no haya indicios de esta falla para la persona que llama.

Un ejemplo sencillo:

INSERT INTO t1 VALUES (1/0)  
INSERT INTO t2 VALUES (1/1)  
SELECT 'Everything is fine' 

Este código se ejecute 'éxito' con XACT_ABORT OFF, y se terminará con un error con XACT_ABORT ON ('INSERT INTO t2' no se ejecutará, y una aplicación cliente levantará una excepción).

Como un enfoque más flexible, puede marcar @@ ERROR después de cada instrucción (vieja escuela), o usar bloques TRY ... CATCH (MSSQL2005 +). Personalmente, prefiero configurar XACT_ABORT cuando no haya motivos para un manejo avanzado de errores.

3

En cuanto a los tiempos de espera del cliente y el uso de XACT_ABORT para manejarlos, en mi opinión hay al menos una muy buena razón para tener tiempos de espera en las API del cliente como SqlClient, y es proteger el código de aplicación del cliente de interbloqueos en SQL código del servidor En este caso, el código del cliente no tiene ninguna falla, pero tiene que protegerse del bloqueo para siempre esperando que el comando se complete en el servidor. Por lo tanto, si los tiempos de espera de los clientes deben existir para proteger el código del cliente, XACT_ABORT ON debe proteger el código del servidor de los abortos del cliente, en caso de que el código del servidor tarde más en ejecutarse de lo que el cliente está dispuesto a esperar.

Cuestiones relacionadas