一个事务

一个事务


SQL Server中事务具有原子性(atomicity),就是说一个事务的所有命令必须作为一个完整的单元执行,要么全部成功,要么全部失败。事务执行的过程中,SQL Server先将所有的数据修改写入到日志中,待事务结束时判断是否需要写入到数据库中。
本文要讨论的问题是:如何定义一个事务,或者说一个事务的范围有多大。一个事务的范围主要受事务模式的影响,不同模式下定义事务不同;同时存储过程和触发器也会嵌套和扩展事务,下面来分别讨论。

一.事务模式
SQL Server支持三种事务模式:

一个显式/隐式事务可以嵌套一个或者多个显式事务。SQL Server有一个变量@@TRANCOUNT,它专门记录着当前活动事务数(即事务的嵌套层数)。@@TRANCOUNT为0表示无事务,1表示一层事务,2表示二层事务….

1.显式事务
显式事务由BEGIN TRAN开始,以ROLLBACK TRAN或COMMIT TRAN结束。COMMIT TRAN提交事务时会将真正的修改写入到数据库中;ROLLBACK TRAN将回滚所有的动作,同时不会作真正的修改。当BEGIN TRAN显式开始一个事务,@@TRANCOUNT从0变成1,每嵌套一次BEGIN TRAN,@@TRANCOUNT增加1,每一次COMMIT TRAN,@@TRANCOUNT减少1,只有从1变为0时,SQL Server才会真正地将修改写入数据库(见图1)。和COMMIT TRAN不同,用ROLLBACK TRAN回滚事务时,@@TRANCOUNT会直接减为0,并实现回滚至最外层的事务(见图2)。注意:若在@@TRANCOUNT为0时调用COMMIT TRAN或ROLLBACK TRAN会报错。(下同)

图1

 

图2


2.隐式事务
隐式事务主要是为了同其他主要RDBMS系统,如ORACLE或DB2相兼容。隐式事务不需要BEGIN TRAN语句,相反,它在第一个语句处开始,直至COMMIT TRAN或ROLLBACK TRAN语句。下一个事务则继续从下一条语句开始。

SQL Server默认状态下是隐式事务是关闭的。可以通过下面的语句打开或关闭默认事务选项:SET IMPLICIT_TRANSACTIONS ON|OFF

隐式事务时,下面的任何一条语句,都会初始化一个事务,我们可称之为隐式事务语句:

事务会据需进行,直至COMMIT或ROLLBACK。注意,隐式事务选项只会对当前的连接产生影响——对任何其他的用户来说该选项仍然是关闭的,除非他们也执行了该SET语句。
理解隐式事务其实也很简单:其相当于开始一个新事务的隐式事务语句前运行了BEGIN TRAN,后面的所有一切都跟显式事务一样。因此,隐式事务中也可以嵌套显式事务。(见图3)

图3

小提示:若开启隐式事务后,事务第一条指令为BEGIN TRAN则会先初始化一个隐式事务,然后嵌套一个显式事务。如下例:

SET IMPLICIT_TRANSACTIONS ON 
BEGIN TRAN  --隐式事务模式下,开始一显式事务
SELECT @@TRANCOUNT --计数为2
COMMIT TRAN
SELECT @@TRANCOUNT --计数为1
COMMIT TRAN –由1变为0,真正的提交
SELECT @@TRANCOUNT --计数为0

3.自动提交事务
SQL Server缺省事务模式为自动提交事务:每一条单独的语句都是一个事务。一个语句要么全部执行成功,要么全部执行失败。
上面讨论了三种事务模式,由此就可以明确的看出每个事务的范围。

二.储存过程和触发器的影响
触发器和储存过程会引起事务的嵌套和扩展。我们将调用后@@TRANCOUNT不变称为事务的扩展;将@@TRANCOUNT的增加称为嵌套。到底是嵌套还是扩展受调用时@@TRANCOUNT值的影响,下表是调用前后@@TRANCOUNT的变化表:

1.触发器的执行
自动提交事务中当@@TRANCOUNT为0时,不管是INSTEAD OF触发器还是AFTER触发器都会引起事务的嵌套。进入触发器时就相当于BEGIN TRAN使得@@TRANCOUNT增加1。触发器结束的时候相当于COMMIT TRAN,使得@@TRANCOUNT减1。当@@TRANCOUNT大于0时,比如显式或隐式事务中的触发器则会引起事务的扩展,不会造成@@TRANCOUNT值的变换。

若触发器中调用ROLLBACK TRAN,则会回滚至最外层事务(不管是显式、隐式还是自动提交事务)。触发器中若调用BEGIN TRAN,则必须配套使用COMMIT TRAN或ROLLBACK TRAN。否则会造成事务永远不会结束、不会提交。由此我们也可看出一个语句的所有的触发器(包括INSTEAD OF语句还是所有的AFTER触发器)都是属于同一个事务。

2.存储过程的执行
EXEC执行储存过程在所有事务模式下@@TRANCOUNT值都不变;但是SQL Server2005中INSERT INTO ..EXEC执行存储过程时和触发器相一样:自动提交事务模式@@TRANCOUNT为0时,引起事务的嵌套,进入存储过程时@@TRANCOUNT加1,退出时减1;当@@TRANCOUNT大于0时,引起事务的扩展。
存储过程中ROLLBACK TRAN不能回滚至本存储过程外的事务,存储过程执行后不能改变@@TRANCOUNT的值,也是说:这个存储过程中BEGIN TRAN和COMMIT TRAN或ROLLBACK TRAN必须相配。

参考文献
1.http://msdn.microsoft.com/en-us/library/ms187844.aspx

2.SQL Server2005高级程序设计

3.http://www.codeproject.com/KB/database/sqlservertransactions.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值