Toto je naše šablona (protokolování chyb odstraněno)
Toto je navrženo tak, aby zvládlo
- Článek Paula Randala "Na serveru SQL neexistuje žádná taková věc jako vnořená transakce"
- Chyba 266
- Vrácení spouštěče
Vysvětlení:
-
všechny TXN begin a commit/rollbacks musí být spárovány tak, aby
@@TRANCOUNT
je stejný na vstupu i výstupu -
neshody
@@TRANCOUNT
způsobit chybu 266, protože-
BEGIN TRAN
přírůstky@@TRANCOUNT
-
COMMIT
sníží@@TRANCOUNT
-
ROLLBACK
vrátí@@TRANCOUNT
na nulu
-
-
Nemůžete snížit
@@TRANCOUNT
pro aktuální rozsah
To je to, co si myslíte, že je "vnitřní transakce" -
SET XACT_ABORT ON
potlačí chybu 266 způsobenou neshodou@@TRANCOUNT
A také se zabývá podobnými problémy "Časový limit transakce SQL Serveru" na dba.se -
To umožňuje TXN na straně klienta (jako LINQ) Jedna uložená procedura může být součástí distribuované transakce nebo transakce XA, nebo jednoduše iniciovaná v kódu klienta (řekněme .net TransactionScope)
Použití:
- Každý uložený proces musí odpovídat stejné šabloně
Shrnutí
- Nevytvářejte tedy více TXN, než potřebujete
Kód
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
Poznámky:
-
Kontrola vrácení zpět je ve skutečnosti nadbytečná, protože
SET XACT_ABORT ON
. Cítím se však díky němu lépe, vypadá bez něj divně a umožňuje situace, kdy ho nechcete mít zapnutý -
Remus Rusanu má podobný shell který používá body uložení. Preferuji volání atomické DB a nepoužívám dílčí aktualizace jako jejich článek