被 MyBatis 缓存坑了,各位可以来了解下 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lxy
V2EX    Java

被 MyBatis 缓存坑了,各位可以来了解下

  •  
  •   lxy 2020 年 6 月 11 日 4031 次点击
    这是一个创建于 2130 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Debug 了半天。

    SpringBoot + MyBatis,默认配置,你觉得下述代码可能有何问题?

    @Transactional public void some_service(List<Person> persons) { for (Person person : persons) { List<Card> cards = dao.findByCardIds(person.getCardIds()); do_someting(cards); } } 

    注意 MyBatis 有缓存机制,在同一 SqlSession 中默认开启,每次非事务查询用的都是新建的 SqlSession,所以缓存不生效。

    但当开启事务时,spring 会使用同一个 SqlSession 做查询,此情况下一级缓存生效。

    例子中,如果程序对查询结果 list 进行了修改操作,那么缓存中的 list 也会相应变化。

    第二次查询时若参数相同(比如 for 循环的是两个相同的 person ),会将缓存中的已被修改过的 list 取出。

    取出的污染数据可能导致后续代码流程错误。

    解决方法是在 Mapper 设置 flushCache="true"。

    总结一下设计缺陷:

    1. 默认配置下,缓存表现不一致。如果非事务查询无缓存,那么事务性查询也应该无缓存。

    2. 缓存未做读取时拷贝( copy on read )。由于缓存返回的是结果集的引用,如果后续代码修改了结果集,将导致缓存污染。

    12 条回复    2020-06-11 18:14:58 +08:00
    cubecube
        1
    cubecube  
       2020 年 6 月 11 日 via Android
    这不叫被坑,这叫没搞清楚机制,系统出了 bug
    wysnylc
        2
    wysnylc  
       2020 年 6 月 11 日
    xuanbg
        3
    xuanbg  
       2020 年 6 月 11 日
    查询瞎用什么事务……
    PopRain
        4
    PopRain  
       2020 年 6 月 11 日
    事务里面,难道不应别人不能修改,用缓存的没有错。。。。 不要乱开事务
    lxy
        5
    lxy  
    OP
       2020 年 6 月 11 日
    @cubecube 这是设计有坑

    @wysnylc 我说的是一级缓存,默认开启的

    @xuanbg 只是举个例子,不是实际情况
    luckyrayyy
        6
    luckyrayyy  
       2020 年 6 月 11 日
    这是设计特性,不是 bug 啊...
    aragakiyuii
        7
    aragakiyuii  
       2020 年 6 月 11 日 via Android
    这不是设计缺陷
    如果业务上 cardId 会重复的话应该在循环外面把 cardId 取出来放到 set 里,再去循环 cardId set
    DJQTDJ
        8
    DJQTDJ  
       2020 年 6 月 11 日
    如果是 bug 的话,就不会公开 flushCache="true"的方法了
    dayformyjob
        9
    dayformyjob  
       2020 年 6 月 11 日
    每次查询用最新的,flushCache="true",或者 useCache="false"
    YoRuo
        10
    YoRuo  
       2020 年 6 月 11 日
    不是 bug 。。。。
    BBCCBB
        11
    BBCCBB  
       2020 年 6 月 11 日
    是 feature
    BBCCBB
        12
    BBCCBB  
       2020 年 6 月 11 日
    在高级别的事务隔离级别下, 是有可重复读的特性的, mybatis 事务缓存了同样的查询
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     861 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 20:44 PVG 04:44 LAX 13:44 JFK 16:44
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86