嵌套事务
舒适 S49883
一.事务
定义:事务是Sql Server的最小工作单元,每一个Sql语句就是一个事务,将工作单元指定为事务必须有四个属性,即ACID标准:
原子性:事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。
一致性:事务在完成时,必须使所有的数据都保持一致状态。
隔离性:该事务对数据库进行的更改对其它事务来说是不可见的,其它事务只会看到事务提交之前或之后的状态数据,其它事务不会查看中间状态的数据。
持久性:事务完成之后,它对于系统的影响是永久性的。
二.嵌套事务
Sql Server支持嵌套事务:也就是说在前一事务未完成之前可启动一个新的事务,只有在外层的Commit Tran语句才会导致数据库的永久更改。
请尝试执行以下语句:
BEGIN TRAN
BEGIN TRAN
ROLLBACK TRAN
ROLLBACK TRAN
执行结果:服务器: 消息 3903,级别 16,状态 1,行 5
ROLLBACK TRANSACTION 请求没有对应的 BEGIN TRANSACTION。
原因分析:
1) Sql Server把每个连接开启的事务数目记录在全局变量@@trancount中,就象计数器一样,
每个Begin Tran语句会让@@trancount自增1,每个Commit Tran语句会让@@trancount自减1,只有最外层的Commit Tran(当@@trancount=1)会将更改影响到数据库中,而不再存储在事务日志中。
2) 非常遗憾的是,不管嵌套的事务层次有多深,不带保存点的Rollback Tran语句将直接把@@trancount设置为0
解决思路:
1) 采用命名事务:可以对事务语句进行命名,让我们先尝试直接使用命名事务来解决刚才的那个问题:
执行语句:
BEGIN TRAN A
BEGIN TRAN B
ROLLBACK TRAN B
ROLLBACK TRAN A
执行结果:服务器: 消息 6401,级别 16,状态 1,行 3
无法回滚 B。没有到任何该名称的事务或保存点。
原因分析:这是个美丽的误会, Sql Server只会记录外层事务名称,如果企图回滚任一内层事务,错误就会出现。
2) 采用保存点:Sql Server提供了一种用于回滚部分事务的机制:Save Tran ,它不会对@@trancount产生任何影响,只是标记回滚事务时可以到达的点。
--定义一个是否为嵌套事务的标志
DECLARE @nestedFlag BIT
IF(@@trancount>0)
BEGIN
--是嵌套事务:使用保存点,避免再次嵌套
SET @nestedFlag=1
SAVE TRAN TestA
END
ELSE
BEGIN
--不是嵌套事务:开启一个事务
SET @nestedFlag=0
BEGIN TRAN TestA
END
--执行业务操作,如果出错就回滚事务点,并立即返回
IF(@@error<>0)
BEGINspringframework事务
ROLLBACK TRAN TestA
RETURN 0
END
--如果不是嵌套事务才提交
IF(@nestedFlag=0)
BEGIN
COMMIT TRAN TestA
END
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论