跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 被 MyBatis 缓存坑了,各位可以来了解下
未分類
20 5 月 2020

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

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

資深大佬 : lxy 11

Debug 了半天。

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

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

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

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

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

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

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

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

总结一下设计缺陷:

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

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

大佬有話說 (12)

  • 資深大佬 : cubecube

    这不叫被坑,这叫没搞清楚机制,系统出了 bug

  • 資深大佬 : wysnylc

    https://blog.csdn.net/isea533/article/details/44566257
    只是你不知道而已

  • 資深大佬 : xuanbg

    查询瞎用什么事务……

  • 資深大佬 : PopRain

    事务里面,难道不应别人不能修改,用缓存的没有错。。。。 不要乱开事务

  • 主 資深大佬 : lxy

    @cubecube 这是设计有坑

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

    @xuanbg 只是举个例子,不是实际情况

  • 資深大佬 : luckyrayyy

    这是设计特性,不是 bug 啊…

  • 資深大佬 : aragakiyuii

    这不是设计缺陷
    如果业务上 cardId 会重复的话应该在循环外面把 cardId 取出来放到 set 里,再去循环 cardId set

  • 資深大佬 : DJQTDJ

    如果是 bug 的话,就不会公开 flushCache=”true”的方法了

  • 資深大佬 : dayformyjob

    每次查询用最新的,flushCache=”true”,或者 useCache=”false”

  • 資深大佬 : YoRuo

    不是 bug 。。。。

  • 資深大佬 : BBCCBB

    是 feature

  • 資深大佬 : BBCCBB

    在高级别的事务隔离级别下, 是有可重复读的特性的, mybatis 事务缓存了同样的查询

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具