Detta är vår mall (felloggningen har tagits bort)
Detta är designat för att hantera
- Paul Randals artikel "Inget sådant som en kapslad transaktion i SQL Server"
- Fel 266
- Utlösa återställanden
Förklaringar:
-
alla TXN-starter och commit/rollbacks måste paras så att
@@TRANCOUNT
är detsamma vid in- och utpassering -
felmatchningar av
@@TRANCOUNT
orsaka fel 266 eftersom-
BEGIN TRAN
ökar@@TRANCOUNT
-
COMMIT
minskar@@TRANCOUNT
-
ROLLBACK
returnerar@@TRANCOUNT
till noll
-
-
Du kan inte minska
@@TRANCOUNT
för den aktuella omfattningen
Detta är vad du skulle tro är den "inre transaktionen" -
SET XACT_ABORT ON
undertrycker fel 266 orsakat av felmatchade@@TRANCOUNT
Och hanterar även problem som detta "SQL Server Transaction Timeout" på dba.se -
Detta tillåter TXN på klientsidan (som LINQ) En enskild lagrad procedur kan vara en del av en distribuerad eller XA-transaktion, eller helt enkelt en som initieras i klientkoden (säg .net TransactionScope)
Användning:
- Varje lagrad proc måste följa samma mall
Sammanfattning
- Så skapa inte fler TXN än du behöver
Koden
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
Anmärkningar:
-
Återställningskontrollen är faktiskt överflödig på grund av
SET XACT_ABORT ON
. Men det får mig att må bättre, ser konstigt ut utan och tillåter situationer där du inte vill ha den på -
Remus Rusanu har ett liknande skal som använder spara poäng. Jag föredrar ett atomic DB-anrop och använder inte partiella uppdateringar som deras artikel