• 请不要在回答技术问题时复制粘贴 AI 生成的内容
echooo0
V2EX  ›  程序员

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

  •  
  •   echooo0 · Apr 27, 2021 · 2687 views
    This topic created in 1864 days ago, the information mentioned may be changed or developed.

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

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

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

    Supplement 1  ·  Apr 27, 2021
    又操作试了下,可能发现问题所在了,应该是因为之前在读取的时候用错了对象导致的(没有用 select 出来的那个新对
    象)

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

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

    感兴趣的可以研究一下

    https://tech.meituan.com/2018/01/19/mybatis-cache.html
    https://www.cnblogs.com/nuccch/p/9107880.html
    15 replies    2021-04-27 15:29:41 +08:00
    xiaoxinshiwo
        1
    xiaoxinshiwo  
       Apr 27, 2021
    额,同一个会话 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  
       Apr 27, 2021
    这好像既不属于幻读也不属于不可重复读
    keepeye
        3
    keepeye  
       Apr 27, 2021
    也有可能是读写分离导致的?
    echooo0
        4
    echooo0  
    OP
       Apr 27, 2021
    @xiaoxinshiwo 我看了下这块资料,mybatis 的二级缓存,在默认的设置中 SELECT 语句不会刷新缓存,

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