Esta es nuestra plantilla (se eliminó el registro de errores)
Esto está diseñado para manejar
- El artículo de Paul Randal "Ninguna transacción anidada en SQL Server"
- Error 266
- Activar retrocesos
Explicaciones:
-
todos los inicios TXN y compromisos/retrocesos deben emparejarse para que
@@TRANCOUNT
es el mismo a la entrada y a la salida -
discrepancias de
@@TRANCOUNT
causa el error 266 porque-
BEGIN TRAN
incrementos@@TRANCOUNT
-
COMMIT
decrementa@@TRANCOUNT
-
ROLLBACK
devuelve@@TRANCOUNT
a cero
-
-
No puede decrementar
@@TRANCOUNT
para el alcance actual
Esto es lo que pensaría que es la "transacción interna" -
SET XACT_ABORT ON
suprime el error 266 causado por@@TRANCOUNT
no coincidentes
Y también se ocupa de problemas como este "SQL Server Transaction Timeout" en dba.se -
Esto permite TXN del lado del cliente (como LINQ) Un solo procedimiento almacenado puede ser parte de una transacción distribuida o XA, o simplemente uno iniciado en el código del cliente (por ejemplo, .net TransactionScope)
Uso:
- Cada proceso almacenado debe ajustarse a la misma plantilla
Resumen
- Así que no cree más TXN de los que necesita
El código
CREATE PROCEDURE [Name]
AS
SET XACT_ABORT, NOCOUNT ON
DECLARE @starttrancount int
BEGIN TRY
SELECT @starttrancount = @@TRANCOUNT
IF @starttrancount = 0
BEGIN TRANSACTION
[...Perform work, call nested procedures...]
IF @starttrancount = 0
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 AND @starttrancount = 0
ROLLBACK TRANSACTION;
THROW;
--before SQL Server 2012 use
--RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO
Notas:
-
La verificación de reversión es realmente redundante debido a
SET XACT_ABORT ON
. Sin embargo, me hace sentir mejor, se ve raro sin él y permite situaciones en las que no lo quieres -
Remus Rusanu tiene un shell similar que utiliza puntos de guardado. Prefiero una llamada de base de datos atómica y no uso actualizaciones parciales como su artículo