MS-SQL 如何处理嵌套事务

相关SQL语句:

BEGIN TRAN

 

SAVE TRAN

 

COMMIT TRAN

 

ROLLBACK TRAN

 

嵌套事务示例:

BEGIN TRAN Tran1

BEGIN TRAN Tran2

  1. COMMIT TRAN 可以单独指定某个事务名,如Tran1,Tran2进行提交。其实也没什么效果,即使Tran2提交成功了,只要将外层事务Tran1回滚,Tran2保存的数据照样被回滚!
  2. ROLLBACK TRAN 不能指定某个事务名进行回滚!只能ROLLBACK TRAN 或者 ROLLBACK TRAN Tran1,也就说只能回滚最外层的事务名。如果执行ROLLBACK TRAN Tran2,SQL会提示“无法回滚 Tran2。找不到该名称的事务或保存点”,出错的原因就是因为Tran2不是最外层事务。总结一句话:ROLLBACK 要么就所有事务都回滚,要么就回滚时异常,一个事务都没回滚!
  3. ROLLBACK 可以回滚某个事务保存点(SAVE TRAN TranSave1), 如ROLLBACK TRAN TranSave1,但是要明白的是,回滚事务保存点并不会使事务数@TranCount减少,你嵌套了几个事务,它还是有几个事务数.
  4. 特别注意,如果在父存储过程创建一个事务Tran1,然后在子存储过程执行ROLLBACK TRAN后,子存储过程会抛出异常!事务只能在同一个存储过程里面创建、回滚和提交,不允许分离在不同的存储过程里面。

基于以上特点,我个人觉得嵌套事务的作用不大,SQL的内部处理其实最终就是处理一个最外层的事务点。SQL抛出事务相关的异常,并不是代码有何问题,而是在提醒我们注意事务的控制。 我们只要采用TRY CATCH 方式捕获相关异常就可以,我们只要确保设计的事务点能正常回滚或提交就OK了。

解决方法1:

  TRY CATCH 捕获相关异常

解决方法2:

  如果外部已经有事务了,就不再创建内部事务。我想SQL的事务异常提醒就是为了告诉你,不能随便一个地方放事务。

  IF @TRANCOUNT =0

        BEGIN TRAN

TRY CATCH 注意事项:

  • SQL语句不加try catch,即使出现异常,后续的SQL语句也会执行。但是一旦外部加了try catch,则会捕获异常,导致后续的SQL语句没有执行。
  • 是否SQL的异常有分致命和普遍的,在没加try catch的情况下,普通的可以继续往下走,但是致命的就不往下走了。这个和C#编程语言有重大的不同,编程语言一旦出现异常,后续代码就不再执行!

在处理嵌套事务时,要特别注意,不论如何要确保事务被完整的关闭或被回滚!

  • 回滚比较好控制。无论有多少级事务数,只要ROLLBACK 一次就可以。不过如果是ROLLBACK TRAN TRANNAME,TranName不是第一级的话,则会出现异常,等于没有执行ROLLBACK操作。
  • 提交就要特别注意了。BEGIN TRAN 创建事务3个,则必须COMMIT TRAN 提交事务3次,才能确保事务数被完整提交。可以通过@@TRANCOUNT来查看当前事务数。一旦存储过程没有完整提交事务,则可能出现事务锁表的情况!如果创建事务的进程销毁了,即使有未提交的事务,应该也销毁,算回滚了吧?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值