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

关于 mysql 数据读取不一致的问题

  •  
  •   echooo0 · 2021-04-27 11:24:44 +08:00 · 2016 次点击
    这是一个创建于 1300 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在问题是这样的,spring 没有开启 @Transactional 的事务,一个函数内,代码上面执行 mysql 的 update 操作,下

    面执行了 select 操作,然后 select 返回的数据是 update 之前的,这种的话,是属于幻读还是不可重复读啊? spring 的

    事务应该怎么设置比较好?

    第 1 条附言  ·  2021-04-27 15:24:18 +08:00
    又操作试了下,可能发现问题所在了,应该是因为之前在读取的时候用错了对象导致的(没有用 select 出来的那个新对
    象)

    不好意思,这个错误确实有点低级 = =。。。。

    所以这里的问题应该不是 mybatis 的缓存问题,关于 mybatis 的一二级缓存怎么设计的,找到了两篇文章写得挺不错的,

    感兴趣的可以研究一下

    https://tech.meituan.com/2018/01/19/mybatis-cache.html
    https://www.cnblogs.com/nuccch/p/9107880.html
    15 条回复    2021-04-27 15:29:41 +08:00
    xiaoxinshiwo
        1
    xiaoxinshiwo  
       2021-04-27 11:33:19 +08:00
    额,同一个会话 mybaties 有缓存的,在 xml 里面设置强制刷新就好了
    flushCache Setting this to true will cause the local and 2nd level caches to be flushed whenever this statement is called. Default: false for select statements.
    useCache Setting this to true will cause the results of this statement to be cached in 2nd level cache. Default: true for select statements.
    https://mybatis.org/mybatis-3/sqlmap-xml.html#select
    SjwNo1
        2
    SjwNo1  
       2021-04-27 11:40:34 +08:00
    这好像既不属于幻读也不属于不可重复读
    keepeye
        3
    keepeye  
       2021-04-27 11:44:17 +08:00
    也有可能是读写分离导致的?
    echooo0
        4
    echooo0  
    OP
       2021-04-27 11:50:30 +08:00
    @xiaoxinshiwo 我看了下这块资料,mybatis 的二级缓存,在默认的设置中 SELECT 语句不会刷新缓存,

    insert/update/delte 会刷新缓存,那么 update 已经刷新了缓存的话,select 出来值应该就是 update 之后的值才对吧?
    echooo0
        5
    echooo0  
    OP
       2021-04-27 11:50:45 +08:00
    @keepeye 没有涉及到这块哦
    xiaoxinshiwo
        6
    xiaoxinshiwo  
       2021-04-27 11:52:08 +08:00
    @echooo0 同一个会话 mybaties 有缓存的
    xiaoxinshiwo
        7
    xiaoxinshiwo  
       2021-04-27 11:53:07 +08:00
    @echooo0 flushCache 设置为 true 看下效果就知道了
    timethinker
        8
    timethinker  
       2021-04-27 12:03:45 +08:00
    建议看一下数据库内的数据实际上到底有没有更新数据。
    然后在检查方法缓存的问题。
    另外如果两个操作不是在一个线程内同步进行的(顺序执行),在异步的情况下有可能会导致第二个比第一个先执行,虽然几率很小,但很多情况下都是由于微小的失误造成的。
    echooo0
        9
    echooo0  
    OP
       2021-04-27 12:11:05 +08:00
    @qwe520liao
    1.数据库的数据最后更新了,大概比 select 操作稍微延迟一点。
    2.是在一个线程内执行的(同步)
    echooo0
        10
    echooo0  
    OP
       2021-04-27 12:15:00 +08:00
    @echooo0 关于第一个补充下,就是在另外一个函数去执行 select 操作发现数据更新了
    wugq
        11
    wugq  
       2021-04-27 12:37:19 +08:00
    可重复读(Repeatable read): 在同一个事务内的查询都是事务开始时刻一致的,也就是重复读取的数据都是一样的。InnoDB 的默认隔离级别。在 SQL 标准中,该隔离级别消除了不可重复读,但是还存在幻读。
    leafre
        12
    leafre  
       2021-04-27 12:42:50 +08:00
    @wugq spring 审题,不在一个事务内
    rationa1cuzz
        13
    rationa1cuzz  
       2021-04-27 15:13:18 +08:00
    看着像是第二次 select session 才 commit
    buster
        14
    buster  
       2021-04-27 15:21:45 +08:00
    楼主有结论了吗?
    同步的代码,update 会返回状态码,正常来说代表其实已经更新成功了,再去读就是新的数据。
    可能 1,会不会其他地方也有 update 操作,内存里的对象引用被修改掉了。
    可能 2,存在并发调用的问题。
    echooo0
        15
    echooo0  
    OP
       2021-04-27 15:29:41 +08:00
    @buster 大概有结论了,可以看上面 append 的内容
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   891 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 20:32 · PVG 04:32 · LAX 12:32 · JFK 15:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.