当前位置: 代码网 > it编程>编程语言>Java > MyBatis 的一级缓存导致的数据一致性问题分析及解决方法

MyBatis 的一级缓存导致的数据一致性问题分析及解决方法

2025年06月24日 Java 我要评论
问题说明下面一段示例的业务逻辑代码:@transactional(propagation = propagation.required, rollbackfor = exception.class)@

问题说明

下面一段示例的业务逻辑代码:

@transactional(propagation = propagation.required, rollbackfor = exception.class)
@override
public void flushorderdetail(flushform form) {
    // 构建批量更新订单状态的参数集合
    list<flushorderparam> flushorderparamlist = payservice.createflushparam(form);
    // 查询出本次需要更新的订单记录
    list<orderentity> orderlist = orderservice.query(form);
    sqlsession sqlsession = null;
    try {
        // 采用mybatis批处理模式,开启批量执行的sqlsession
        sqlsession = sqlsessionfactory.opensession(executortype.batch);
        // 批量处理订单状态信息
        orderservice.batchupdate(sqlsession, flushorderparamlist, orderlist);
        // 提交批量处理事务
        sqlsession.commit();
    } catch (exception e) {
        // 出现异常时,回滚批处理操作
        log.error("批处理订单状态失败", e);
        if (sqlsession != null) sqlsession.rollback();
        // 将异常抛出,触发spring事务管理的回滚机制
        throw e;
    } finally {
        // 关闭sqlsession,释放资源
        if (sqlsession != null) {
            try {
                sqlsession.close();
            } catch (exception e) {
                log.error("关闭sqlsession异常", e);
            }
        }
    }
    // 批量操作成功后,再次查询订单,打印订单状态日志,便于排查和验证
    orderlist = orderservice.query(form);
    for (orderentity order : orderlist) {
        logger.debug("订单 {} 状态 {}", order.getordercode(), order.getstatus());
    }
}

上面这段spring业务代码主要内容就是想根据参数批量更新订单状态,里面使用了spring的事务注解,同时方法中另外开启了一个数据库会话用于批处理更新,这样可以加快速度。

这段代码连接的数据库是 mysql, 且事务隔离级别为 提交读 (read-committed),查询mysql事务隔离方法如下:

select @@session.transaction_isolation;

问题现象:
orderlist = orderservice.query(form); 查询出来的订单状态没有变化,但是数据库中已经更新 !

问题原因

并非ai 给出的回答:因为两个不同的事务管理器导致不一样的结果…

首先,在提交读的隔离级别下,即便不同的事务管理器也可以相互读取到对方数据库会话 已经提交的事务数据

那为什么读取到的最后状态没有变化? 因为 mybatis 一级缓存导致

  • mybatis 一级缓存默认绑定在一个 sqlsession 的生命周期内下,
  • 上面代码中的开头和结尾的 orderservice.query(form) 是在同一个sqlsession生命周期下
  • 且查询参数一样,这样导致两次查询结果一样,但数据库中其实已经状态更新了

问题解决

修改一级缓存的隔离级别为 ·statement· 级别,这样等同于关闭一级缓存。

mybatis:
  type-aliases-package: com.middol.*.model.**.dao
  mapper-locations: classpath:mapper/**/*mapper.xml
  configuration:
    map-underscore-to-camel-case: true # 开启驼峰功能
    local-cache-scope: statement

主要关注 local-cache-scope: statement

或者上面代码放弃使用批处理模式,采用同一个sqlsession下操作数据库,
或者直接使用批处理的sqlsession查询订单表。

到此,问题原因和处理说明完毕!

到此这篇关于mybatis 的一级缓存导致的数据一致性问题分析的文章就介绍到这了,更多相关mybatis一级缓存导致数据一致性内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com