Sql Server支持嵌套事务:也就是说在前一事务未完成之前可启动一个新的事务,只有在外层的Commit Tran语句才会导致数据库的永久更改。
请尝试执行以下语句:
BEGIN TRAN tr0
BEGIN TRAN tr1
ROLLBACK TRAN tr1
ROLLBACK TRAN tr0
执行结果:服务器: 消息 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) Sql Server只会记录外层事务名称如果企图回滚任一内层事务,错误就会出现。
3) 非常遗憾的是,不管嵌套的事务层次有多深,不带保存点的Rollback Tran语句将直接把@@trancount设置为0
解决思路:
1) 采用保存点:Sql Server提供了一种用于回滚部分事务的机制:Save Tran ,它不会对@@trancount产生任何影响,只是标记回滚事务时可以到达的点。