sql server - Rollback transaction from called stored procedure -
i have simple scenario: logger procedure , main procedure logger called. trying rollback transaction inside logger started in main, getting errors. not sure why. here 2 procs , error message receive:
create procedure splogger begin if @@trancount > 0 begin print @@trancount rollback end end go create procedure spcaller begin begin try begin transaction raiserror('', 16, 1) commit transaction end try begin catch exec splogger end catch end go exec spcaller 1 msg 266, level 16, state 2, procedure splogger, line 15 transaction count after execute indicates mismatching number of begin , commit statements. previous count = 1, current count = 0.
1) error message clear: number of active txs @ end of sp should same number of active txs @ beginning.
so, when @ execution of dbo.splogger begins number of active txs (@@trancount) 1 if execute within sp rollback statement this'll cancel all active txs , @@trancount becomes 0 -> error/exception
2) if want avoid writing if @@trancount ... rollback within every catch block of every user sp don't it. call dbo.splogger within catch block after rollback.
3) if have call sps other sp using txs use following template (source: rusanu's blog)
create procedure [usp_my_procedure_name] begin set nocount on; declare @trancount int; set @trancount = @@trancount; begin try if @trancount = 0 begin transaction else save transaction usp_my_procedure_name; -- actual work here lbexit: if @trancount = 0 commit; end try begin catch declare @error int, @message varchar(4000), @xstate int; select @error = error_number() , @message = error_message() , @xstate = xact_state(); if @xstate = -1 rollback; if @xstate = 1 , @trancount = 0 rollback if @xstate = 1 , @trancount > 0 rollback transaction usp_my_procedure_name; throw; end catch end with few small changes:
a) set xact_abort on
b) call dbo.splogger within catch block when there @@trancount = 0:
if @@trancount = 0 begin exec dbo.splogger ... params ... end throw -- or raiserror(@message, 16, @xstate) why ? because if dbo.splogger sp insert rows dbo.dbexception table when 1 tx active in case of rollback sql server have rollbacl these rows.
example:
sp1 -call-> sp2 -call-> sp3 |err/ex -> catch & raiserror (no full rollback) <----------- |err/ex -> catch & raiserror (no full rollback) <------------- |err/ex -> catch & full rollback & splogger 4) update
create proc testtx begin begin tran -- b rollback -- c end -- d go -- test begin tran -- - @@trancount = 1 exec dbo.testtx /* number of active txs (@@trancount) @ begining of sp 1 b - @@trancount = 2 c - @@trancount = 0 d - execution of sp ends. sql server checks & generate err/ex transaction count after execute indicates mismatching number of begin , commit statements. previous count = 1, current count = 0. */ commit -- e - because @@trancount 0 statement generates another err/ex commit transaction request has no corresponding begin transaction. -- end of test
5) see autonomous transactions: requires sql2008+.
an autonomous transaction nested transaction inner transaction not affected state of outer transaction. in other words, can leave context of current transaction (outer transaction) , call transaction (autonomous transaction). once finish work in autonomous transaction, can come continue on within current transaction. done in autonomous transaction done , won’t changed no matter happens outer transaction.
Comments
Post a Comment