• Spring编程式事务使用不当导致其他事务无法正常提交


    1.事故背景

    原本在使用的是注解式事务,后面因为需要在事务中增加异步推送机制,所以需要将推送机制放到事务之外,修改后发现系统经常出现事务长时间无法提交导致回滚。

    2.排查流程

    (1)一开始重启应用是能恢复正常,所以肯定是在某种情况下会触发异常的产生

    (2)查看在mysql控制台查看当前正在执行的事务(SELECT * FROM information_schema.INNODB_TRX),分析该sql语句在逻辑上并没有锁竞争的出现,只是单单一条update语句,但事务却没有提交

    (3)这时候确定在业务代码逻辑上不会出现锁竞争,但事务却没有正常提交,所以考虑是mysql连接会话的autoCommit属性为false导致事务无法正常提交

    (4)因异常出现是在讲注解式事务改为编程式事务之后,所以猜测是因为该改动导致异常出现

    3.原理分析

    (1)spring事务支持原理:spring的事务支持原理是先将mysql连接会话的自动提交属性关闭,即将当前会话的autoCommit属性设置为false,然后将该连接绑定到该线程中,在该事务中的所有数据库操作都是使用同一个线程,所有的数据库操作完成后才主动去做commit操作完成事务

    (2)以下为编程式事务出现异常的流程分析的代码示例

    当开启事务时,当前会话的自动提交属性讲被设置为false

     当事务没有提交而是提前return出去时,会话的状态并不会改变,autoCommit属性一直为false,这就导致当其他请求使用该数据库连接会话操作数据库时,事务将无法自动提交,如下图所示,即使没有开启事务,

    autoCommit状态也是为false,所以会导致其他使用该会话的事务无法正常提交

     

     4.改进方式

    (1)避免在未主动commit事务前return出去

    (2)增加finally代码块,判断事务状态,回滚事务即可

    DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
            TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);
            try {
               doSomething();
            } catch (Exception e) {
                transactionManager.rollback(transactionStatus);
                getLogger().error(e.getMessage());
                throw new RuntimeException("系统异常");
            } finally {
                if(null != transactionStatus && !transactionStatus.isCompleted()){
                    transactionManager.rollback(transactionStatus);
                }
            }

     连接恢复源码如下:



  • 相关阅读:
    Eclipse无法启动报An internal error occurred during: "reload maven project". java.lang.NullPointerExceptio错
    axios拦截器
    antd 之TimePicker设置禁用时间
    使用dva和ant-design组件在IE中的兼容问题记录
    Electron对JQuery的支持
    将本地项目上传到github时,问题总结
    ‘时间等待’加载处理
    6、模块和包的导入
    1、python的安装
    3、简单小程序练习
  • 原文地址:https://www.cnblogs.com/xiguadadage/p/13552781.html
Copyright © 2020-2023  润新知