rollback 最后判断成功_疏忽掉rollback异常处理的严重后果

我们知道结束事务,要么用commit,要么用rollback。但是并不代表你敲一个commit或者rollback命令,事务就会百分百结束了。事实证明,即便你没有漏掉commit和rollback。事务照样得不到百分百保障,甚至会出现数据库阻塞。

昨天下班跟同事喝了几瓶啤酒,晚上回到宿舍,没有开电脑,准备用手机背几个英语单词就睡觉。23点左右,在云贵地区实施项目的朋友打来电话。难道邀请我去大理或丽江游玩?有这个想法,看来是酒精上头了,哈哈。

朋友跟我说,遇到一个事务问题需要我帮忙排查,药房有个入库单总共七条明细。第一次入库,系统报错,竟然有六条明细完成了入库,再次入库成功,造成了六条明细重复入库。

思绪只好从苍山洱海一下子回到了广州宿舍。立马打开电脑,远程过去。代码大体看了一遍,事务控制还算严谨,没有找到问题原因。朋友也说反复看了很多遍,没有发现任何代码问题。我俩就这样一行行的代码排查,两个小时过去后,仍然没有发现问题。断开远程,躺在床上,却怎么也睡不着了。一直思考问题到底出在哪里呢?也不知道几点钟睡着了。

早上来到公司,一大堆的事情等着处理,也没来得及再去继续排查昨晚的问题。下午临下班的时候,不死心的我还是想继续排查一下这个问题。联系朋友后,继续远程过去。终于找到了第一次入库失败的原因,程序里面有个bug,当单子里面同时出现多个新药品时,自动增加药品信息的代码有问题,造成失败。因为这张入库单刚好有两个新药品,第一次入库失败,但是加入了一个新药品。第二次入库,新药品就只剩一个了,从而入库成功。找到失败的原因后,继续排查事务被破坏的原因。增加药品信息失败后明明执行了rollback啊,为什么会完成了六条明细的入库呢?因为明细的入库是循环一条条执行的,当执行到第七条报错后,代码执行了rollback。但是事务并没有真正的rollback掉。唯一的可能就是rollback执行失败了。而代码中并没有判断rollback的执行结果,只是执行了rollback就认为事务回滚了。当用户进行后续事务操作的时候,把前面不完整的sql语句一起commit了(事务对象使用的是全局对象)。

思绪回到了很多年前,曾经有朋友问我,commit失败了怎么办,我不假思索地跟他说rollback啊。他接着问我,那如果rollback也失败了呢?当时的我竟无言以对。

我们知道判断commit和rollback是否成功是通过事务对象的sqlcode属性来判断的。打开pb帮助文档,找到了如下代码:

3ac891452eb9b47f8c69612dd31d58bb.png

显然,pb帮助文档也没有commit和rollback失败的处理逻辑。很是失望!

然后在想,pb不处理就不处理吧,看看spring框架是如何处理的。然后就找到了如下代码:

b46d20c46c2e0a0c747db43788ce44ff.png

甚是开心,此处我们可以看到rollback失败后,spring框架会抛出TransactionSystemException异常,此异常属于RuntimeException异常,如果你使用的过程中捕获了此异常需要自己处理异常逻辑,如果你不捕获异常,系统会自动结束当前线程。突然觉得,java的处理逻辑比pb的处理逻辑高了一个档次。

经过比较之后,我们再次回到pb里面的问题,rollback并不能保证百分百的成功!所以,我们必须做出判断,并进行异常逻辑处理。处理逻辑跟spring框架一样,要么自己编写异常处理逻辑,要么停止系统运行,如果上下文环境能够还原的话,最好不要停止系统运行,通过编写逻辑代码将上下文环境还原。如果实在无法还原上下文环境,可以执行事务的断开再重连的办法。当然了,逼到最后,给用户报出友好的错误提示,并且退出系统运行也是不错的选择(概率极低)。我的iphone手机买来之后,莫名其妙的自动重启也有三次了,三年出现三次异常重启,其实还是可以接受的,估计rollback失败的概率跟这个概率也差不多,但是即便概率再低,不去处理,错误该来的还是会来的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值