Dit is onze sjabloon (foutregistratie verwijderd)
Dit is ontworpen om
- Paul Randal's artikel "Er bestaat niet zoiets als een geneste transactie in SQL Server"
- Fout 266
- Trigger terugdraaien
Uitleg:
-
alle TXN-begin- en commit/rollbacks moeten worden gekoppeld zodat
@@TRANCOUNT
is hetzelfde bij in- en uitstappen -
mismatches van
@@TRANCOUNT
fout 266 veroorzaken omdat-
BEGIN TRAN
verhoogt@@TRANCOUNT
-
COMMIT
verlaagt@@TRANCOUNT
-
ROLLBACK
retourneert@@TRANCOUNT
naar nul
-
-
U kunt
@@TRANCOUNT
niet verlagen voor de huidige scope
Dit is wat je zou denken dat de "innerlijke transactie" is -
SET XACT_ABORT ON
onderdrukt fout 266 veroorzaakt door niet-overeenkomende@@TRANCOUNT
En behandelt ook dit soort problemen "SQL Server Transaction Timeout" op dba.se -
Dit maakt TXN's aan de clientzijde mogelijk (zoals LINQ). Een enkele opgeslagen procedure kan deel uitmaken van een gedistribueerde of XA-transactie, of gewoon een procedure die is gestart in klantcode (bijvoorbeeld .net TransactionScope)
Gebruik:
- Elk opgeslagen proces moet voldoen aan dezelfde sjabloon
Samenvatting
- Maak dus niet meer TXN's aan dan u nodig heeft
De code
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
Opmerkingen:
-
De terugdraaicontrole is eigenlijk overbodig vanwege
SET XACT_ABORT ON
. Ik voel me er echter beter door, het ziet er vreemd uit zonder, en zorgt voor situaties waarin je het niet wilt hebben -
Remus Rusanu heeft een vergelijkbare shell die spaarpunten gebruikt. Ik geef de voorkeur aan een atomaire DB-aanroep en gebruik geen gedeeltelijke updates zoals hun artikel