Sqlserver the Transaction to be careful when doing Rollback (reprint)
Carefully studied the case, find sql server inside explicit transaction (display transaction) is still a little complicated. The following are some summary:
Commit transaction commits all nested transaction modification. However, if there are nested transaction rollback tran to save point, then the part after the save point will revert out.
delete from dbo.numbertable begin tran out1 insert into dbo.numbertable values(1) insert into dbo.numbertable values(2) begin tran inn1 insert into dbo.numbertable values(3) insert into dbo.numbertable values(4) save tran inn1SavePoint insert into dbo.numbertable values(5) rollback tran inn1SavePoint commit tran inn1 commit tran out1
@@ TRANCOUNT the session can be used to record the number of the current transaction, for the transaction in terms of nested, it will begin transaction each time plus one, each time it will commit tran minus one. So in the statement which can be checked whether the current at which a transaction through select @@ TRANCOUNT. If the current @@ TRANCOUNT is 0, that statement is wrong to call commit or rollback will appear. In which nested transaction, ROLLBACK is very special, it will be directly set to 0 @@ TRANCOUNT.
begin tran begin tran begin tran print @@trancount rollback tran print @@trancount
For nested transaction terms, rollback wording is very special. If the nest, rollback transaction can not bring back the name of the transaction, is to bring only the outermost transaction name. Rollback will discard all modifications nested transaction before the rollback statement. But after the Rollback update will still submit it wants, because: After the rollback, @@ trancount is 0, then the statement after the rollback does not belong explicit transaction, belong autocmmit transaction, the automatic submission.
delete from dbo.numbertable begin tran t1 insert into dbo.numbertable values(1) begin tran t2 insert into dbo.numbertable values(2) rollback tran print 'after rollback in innert transaction, the transaction count is: '+cast(@@trancount, varchar(5)) insert into dbo.numbertable values(3) --commit tran select * from dbo.numbertable
Stored procedures which can begin transaction, if you call a stored procedure places begin transaction, then this also belongs to the nested transaction, if the result of the stored procedure inside rollback, get the same as above. But one thing special place in time with the end of the stored procedure execution will begin comparing the value of @@ trancount stored procedures and end time of @@ trancount, if not the same, Sqlserver will give a message like "Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION statement is missing. Previous count = 1, current count = 0. "message does not affect the analysis performed thereafter.
CREATE PROCEDURE [dbo].[AddNumber] AS BEGIN begin tran insert into dbo.numbertable values(1) insert into dbo.numbertable values(2) insert into dbo.numbertable values(3) rollback tran END delete from dbo.numbertable begin tran out1 exec dbo.addnumber print @@trancount insert into dbo.numbertable values(3) select * from dbo.numbertable
If you do a rollback in the stored procedure inside, outside to do that commit or rollback is not effective and will complain, because once inside nested transaction transaction calls the rollback, @@ trancount to 0, and on the outside or commit rollback will direct error. Such as sp, I imagine rollback in the outermost, that is wrong, because the rollback statement inside sp. Finally, there will always be inserted into the table value 3.
delete from dbo.numbertable begin tran out1 exec dbo.addnumber print @@trancount insert into dbo.numbertable values(3) rollback tran out1 select * from dbo.numbertable
So for nested transaction terms, transaction if the transaction once the internal rollback, will be left to the outside of a pit. To solve this problem is, there are two solutions:
1. Check the outside of the transaction which @@ trancount, if this value is consistent with the code when you begin tran, that no description of the internal transaction rollback, and that can continue to commit or rollback.
delete from dbo.numbertable begin tran t1 insert into dbo.numbertable values(1) begin transaction t2 insert into dbo.numbertable values(2) rollback tran if @@trancount = 1 begin insert into dbo.numbertable values(3) commit tran end
2. In all internal transaction which can only commit, can not rollback. If you must rollback, how to do that? save point can come in handy. Sp changed like this example:
ALTER PROCEDURE [dbo].[AddNumber] AS BEGIN begin tran save tran pp insert into dbo.numbertable values(1) insert into dbo.numbertable values(2) insert into dbo.numbertable values(3) rollback tran pp commit tran END begin tran out1 exec dbo.addnumber print @@trancount insert into dbo.numbertable values(3) commit tran out1
Carefully studied the case, find sql server inside explicit transaction (display transaction) is still a little complicated. The following are some summary:
Commit transaction commits all nested transaction modification. However, if there are nested transaction rollback tran to save point, then the part after the save point will revert out.
delete from dbo.numbertable begin tran out1 insert into dbo.numbertable values(1) insert into dbo.numbertable values(2) begin tran inn1 insert into dbo.numbertable values(3) insert into dbo.numbertable values(4) save tran inn1SavePoint insert into dbo.numbertable values(5) rollback tran inn1SavePoint commit tran inn1 commit tran out1
@@ TRANCOUNT the session can be used to record the number of the current transaction, for the transaction in terms of nested, it will begin transaction each time plus one, each time it will commit tran minus one. So in the statement which can be checked whether the current at which a transaction through select @@ TRANCOUNT. If the current @@ TRANCOUNT is 0, that statement is wrong to call commit or rollback will appear. In which nested transaction, ROLLBACK is very special, it will be directly set to 0 @@ TRANCOUNT.
begin tran begin tran begin tran print @@trancount rollback tran print @@trancount
For nested transaction terms, rollback wording is very special. If the nest, rollback transaction can not bring back the name of the transaction, is to bring only the outermost transaction name. Rollback will discard all modifications nested transaction before the rollback statement. But after the Rollback update will still submit it wants, because: After the rollback, @@ trancount is 0, then the statement after the rollback does not belong explicit transaction, belong autocmmit transaction, the automatic submission.
delete from dbo.numbertable begin tran t1 insert into dbo.numbertable values(1) begin tran t2 insert into dbo.numbertable values(2) rollback tran print 'after rollback in innert transaction, the transaction count is: '+cast(@@trancount, varchar(5)) insert into dbo.numbertable values(3) --commit tran select * from dbo.numbertable
Stored procedures which can begin transaction, if you call a stored procedure places begin transaction, then this also belongs to the nested transaction, if the result of the stored procedure inside rollback, get the same as above. But one thing special place in time with the end of the stored procedure execution will begin comparing the value of @@ trancount stored procedures and end time of @@ trancount, if not the same, Sqlserver will give a message like "Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION statement is missing. Previous count = 1, current count = 0. "message does not affect the analysis performed thereafter.
CREATE PROCEDURE [dbo].[AddNumber] AS BEGIN begin tran insert into dbo.numbertable values(1) insert into dbo.numbertable values(2) insert into dbo.numbertable values(3) rollback tran END delete from dbo.numbertable begin tran out1 exec dbo.addnumber print @@trancount insert into dbo.numbertable values(3) select * from dbo.numbertable
If you do a rollback in the stored procedure inside, outside to do that commit or rollback is not effective and will complain, because once inside nested transaction transaction calls the rollback, @@ trancount to 0, and on the outside or commit rollback will direct error. Such as sp, I imagine rollback in the outermost, that is wrong, because the rollback statement inside sp. Finally, there will always be inserted into the table value 3.
delete from dbo.numbertable begin tran out1 exec dbo.addnumber print @@trancount insert into dbo.numbertable values(3) rollback tran out1 select * from dbo.numbertable
So for nested transaction terms, transaction if the transaction once the internal rollback, will be left to the outside of a pit. To solve this problem is, there are two solutions:
1. Check the outside of the transaction which @@ trancount, if this value is consistent with the code when you begin tran, that no description of the internal transaction rollback, and that can continue to commit or rollback.
delete from dbo.numbertable begin tran t1 insert into dbo.numbertable values(1) begin transaction t2 insert into dbo.numbertable values(2) rollback tran if @@trancount = 1 begin insert into dbo.numbertable values(3) commit tran end
2. In all internal transaction which can only commit, can not rollback. If you must rollback, how to do that? save point can come in handy. Sp changed like this example:
ALTER PROCEDURE [dbo].[AddNumber] AS BEGIN begin tran save tran pp insert into dbo.numbertable values(1) insert into dbo.numbertable values(2) insert into dbo.numbertable values(3) rollback tran pp commit tran END begin tran out1 exec dbo.addnumber print @@trancount insert into dbo.numbertable values(3) commit tran out1