V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
daimubai
V2EX  ›  Java

求问 Mybatis 的缓存

  •  
  •   daimubai · 2022-01-01 19:39:39 +08:00 · 1752 次点击
    这是一个创建于 1057 天前的主题,其中的信息可能已经有所发展或是发生改变。

    已经将一级缓存设置为了 statement ,关闭了二级缓存

    mybatis:
      configuration:
        cache-enabled: false
        local-cache-scope: statement
    

    测试

        @GetMapping("/test")
        @Transactional
        public User test() throws InterruptedException {
            User user = userMapper.selectById(1);
            System.out.println(user);
            TimeUnit.SECONDS.sleep(5);
            User user2 = userMapper.selectById(1);
            System.out.println(user2);
            return user2;
        }
    

    疑问

    2022-01-01 19:33:18.320 DEBUG 49182 --- [nio-8000-exec-4] com.ding.mapper.UserMapper.selectById    : ==>  Preparing: SELECT * FROM `user` WHERE id = ? 
    2022-01-01 19:33:18.321 DEBUG 49182 --- [nio-8000-exec-4] com.ding.mapper.UserMapper.selectById    : ==> Parameters: 1(Integer)
    2022-01-01 19:33:18.322 DEBUG 49182 --- [nio-8000-exec-4] com.ding.mapper.UserMapper.selectById    : <==      Total: 1
    User(id=1, username=test, password=222, phone=)
    2022-01-01 19:33:23.327 DEBUG 49182 --- [nio-8000-exec-4] com.ding.mapper.UserMapper.selectById    : ==>  Preparing: SELECT * FROM `user` WHERE id = ? 
    2022-01-01 19:33:23.327 DEBUG 49182 --- [nio-8000-exec-4] com.ding.mapper.UserMapper.selectById    : ==> Parameters: 1(Integer)
    2022-01-01 19:33:23.328 DEBUG 49182 --- [nio-8000-exec-4] com.ding.mapper.UserMapper.selectById    : <==      Total: 0
    User(id=1, username=test, password=222, phone=)
    

    日志是打印了两遍 sql ,在休眠的 5 秒前我已经在数据库把这条数据清空了,但是第二次执行的结果返回的还是和第一次一样

    第 1 条附言  ·  2022-01-01 20:19:01 +08:00
    总结:
    Spring 中
    1. mybatis 的一级缓存默认为 session ,但是只有在事务中缓存才会生效,也就是相同的两次查询只会执行一次
    2. 如果碰到这种情况则是隔离级别导致的。修改为 read committed 即可。Spring 的隔离级别默认是和数据库一致的
    如果不想修改数据库的隔离级别,则要在指定 Transactional 中指定 isolation
    5 条回复    2022-01-02 09:57:12 +08:00
    daimubai
        1
    daimubai  
    OP
       2022-01-01 19:41:30 +08:00
    这应该不是 Mybatis 缓存作的怪吧,如果缓存生效的话第二个 sql 应该不会执行才对。

    但是我把事务去掉就可以了,如果非要加事务呢,求大佬指点
    az467
        2
    az467  
       2022-01-01 19:44:50 +08:00   ❤️ 1
    db 隔离级别改为 read committed
    daimubai
        3
    daimubai  
    OP
       2022-01-01 19:48:10 +08:00
    @az467

    show variables like 'transaction%'

    READ-COMMITTED

    大佬,是读已提交的
    daimubai
        4
    daimubai  
    OP
       2022-01-01 20:19:50 +08:00
    @az467 ok 了,问题最后定位到了 Spring 的隔离级别没有使用数据库的,和缓存无关。多谢
    potatowish
        5
    potatowish  
       2022-01-02 09:57:12 +08:00 via iPhone
    一级缓存是 sqlsession 级别的缓存,每次操作数据库会构造不同的 sqlsession 对象,缓存互不影响。

    开启事务后,同一个事务中的数据库访问会复用 sqlsession ,所以会使用同一个缓存
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2738 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 06:12 · PVG 14:12 · LAX 22:12 · JFK 01:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.