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
@@TRANCOUNTes el mismo a la entrada y a la salida -
discrepancias de
@@TRANCOUNTcausa el error 266 porque-
BEGIN TRANincrementos@@TRANCOUNT -
COMMITdecrementa@@TRANCOUNT -
ROLLBACKdevuelve@@TRANCOUNTa cero
-
-
No puede decrementar
@@TRANCOUNTpara el alcance actual
Esto es lo que pensaría que es la "transacción interna" -
SET XACT_ABORT ONsuprime el error 266 causado por@@TRANCOUNTno 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