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

Popular posts from this blog

wordpress - (T_ENDFOREACH) php error -

Export Excel workseet into txt file using vba - (text and numbers with formulas) -

Using django-mptt to get only the categories that have items -