美文网首页
Transactional碰上async

Transactional碰上async

作者: 不二不二熊 | 来源:发表于2020-09-28 23:13 被阅读0次

    业务上线后出现了一个bug: 用户配置/删除课程时,根据已配置课程数据生成栏目树时好时坏,具体表现为:某种时刻刷新的栏目树是数据未入库之前的旧数据。但是全量刷新类目接口稳定不报错,两个公用一个接口。

    查询具体代码发现,刷新类目接口是在课程配置@Transactional中调用了@async调用的异步方法,分析,很有可能是这儿导致,数据未commit完毕,异步刷新类目方法已经调用执行完毕了。

    其中stackoverflow上同样有人提出了相同的问题:

    https://stackoverflow.com/questions/51833306/using-async-inside-a-transaction-in-spring-application

    具体的解决办法,考虑有两种:

    1. 使用event事件机制,当数据全部更新完毕后通知异步方法执行,这是基于观察者模式
    2. 使用TransactionSynchronizationManager,重写其中的 afterCommit 方法,标明在数据commit完毕后执行。

    具体伪代码实现如下:

    public class CourseServiceImpl implements CourseService { 
        
        /**
         * 配置课程
         */
        public void addRealmCourseList(){
         //更新数据库操作
            update();
         //调用异步方式
           executeAfterTransactionCommits(()->{
               //具体异步方法
              ...
            });
        }
        
        /**
         * commit之后执行
         */
        private void executeAfterTransactionCommits(Runnable task) {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCommit() {
                    task.run();
                }
            });
        }
    }
    

    值得注意的是,除去这种异常case之外,@Transactional@Async联合使用还会导致设置的Transaction注解不生效。原因其实也很简单:

    1. Spring 实现这两个注解的方式都是通过AOP
    2. 在实现时,Async注解强制覆盖AOP的order为最小值(它认为Async应该是执行的AOP链中的第一个advisor)
    3. 但是在实现Transactional注解时,却没有覆盖order,这意味着它仍然为默认的Integer.MAX_VALUE,order可配置。所以异步切面会先于事务切面执行。
    4. 假设@Transactional能先于Async切面执行,但由于spring事务管理依赖的是ThreadLocal,所以在开启的异步线程里面感知不到事务,说细点就是在Spring开启事务之后,会设置一个连接到当前线程,但这个时候又开启了一个新线程,执行实际的SQL代码时,通过ThreadLocal获取不到连接就会开启新连接,也不会设置autoCommit,所以这个函数整体将没有事务。

    其中,在spring源码中同样有人提到了这样一个issue,目前已经关闭:

    https://github.com/spring-projects/spring-framework/issues/11806

    由此可见,当我们业务中有需要Transaction与async同时使用时,一定要小心使用。

    相关文章

      网友评论

          本文标题:Transactional碰上async

          本文链接:https://www.haomeiwen.com/subject/zvqsuktx.html