当前位置: 首页 > 知识库问答 >
问题:

java - 如何理解mybatis的一级缓存?会不会造成数据不一致的问题?

万铭
2023-11-10

最近在了解mybatis缓存的时候, 看到了一级缓存, 并且默认是打开的,但是我有一个疑惑:

如有两个SqlSession, 假设叫做a,b; 如果a查询一次, 紧接着b更新一次, 然后此时a再次查询,是不是查询到的还是老数据

所以是不是我对SqlSession理解不到位? 如果两个用户并发在接口上请求, 是不是大概率不在一个SqlSession上? 如果是, 那会不会出现脏读问题?

共有2个答案

从景曜
2023-11-10
如有两个SqlSession, 假设叫做a,b; 如果a查询一次, 紧接着b更新一次, 然后此时a再次查询,是不是查询到的还是老数据

是,这个叫‘可重复读’。

所以是不是我对SqlSession理解不到位? 如果两个用户并发在接口上请求, 是不是大概率不在一个SqlSession上? 如果是, 那会不会出现脏读问题?

不是大概率不在,是不可能在(除非真的自己写了一套奇怪的逻辑,多个请求能访问到同一个 session…),所以也不存在脏读

通常来说,每个请求独享一个数据库连接,一个 sql session,一个事务上下文

柯浩壤
2023-11-10

你的理解基本是对的,MyBatis 确实有一级缓存,并且默认是打开的。这是全局的 SqlSession 级别的缓存。对于你的问题,确实可能会有数据一致性的问题。

让我们详细分析一下你的情况:

  • 当你查询数据时,MyBatis 会首先尝试从一级缓存中获取数据,如果找不到,才会去数据库中查询。
  • 当你有两个 SqlSession,a 和 b,他们对同一数据进行操作时,可能会出现数据不一致的情况。

假设 a 查询了数据并将其存储在它的 SqlSession 的一级缓存中,然后 b 更新了数据并提交到数据库。这时,如果 a 再次查询相同的数据,由于它的 SqlSession 的一级缓存中仍然保存着旧的数据,所以它无法获取到 b 已经更新过的数据。因此,确实可能会出现数据不一致的情况。

解决此问题的一种方式是使用 MyBatis 的二级缓存。二级缓存是跨 SqlSession 的,它可以避免这种数据不一致的情况。你可以在映射文件中开启二级缓存:

<cache/>

当然,脏读问题一般来说只会在一个数据库事务内发生,不同的事务之间不会出现脏读问题。也就是说,如果两个用户并发在接口上请求,他们各自的事务内获取的数据都是一致的,不会相互影响。但是,如果在同一事务内(例如,使用相同的 SqlSession),那么确实可能会出现脏读问题。这通常发生在读取(SELECT)和写入(UPDATE, DELETE, INSERT)操作同时发生时。

 类似资料:
  • 本文向大家介绍深入理解Mybatis一级缓存,包括了深入理解Mybatis一级缓存的使用技巧和注意事项,需要的朋友参考一下 客户端向数据库服务器发送同样的sql查询语句,如果每次都去访问数据库,会导致性能的降低。 那么怎么提高呢? mybatis为我们提供了一级缓存的策略 在一个sqlSession开启和关闭之间,sqlSession对象内部(其实是Executor)会维护一个缓存的对象,当查询数

  • 一级缓存是session级别的缓存,默认开启,当查询一次数据库时,对查询结果进行缓存,如果之后的查询在一级缓存中存在,则无需再访问数据库; 二级缓存是sessionFactory级别的缓存,需要配置才会开启。当进行sql语句查询时,先查看一级缓存,如果不存在,访问二级缓存,降低数据库访问压力。

  • 本文向大家介绍Mybatis 的一级、二级缓存相关面试题,主要包含被问及Mybatis 的一级、二级缓存时的应答技巧和注意事项,需要的朋友参考一下 1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就 将清空,默认打开一级缓存。 2)二级缓

  • 本文向大家介绍说一下 MyBatis 的一级缓存和二级缓存?相关面试题,主要包含被问及说一下 MyBatis 的一级缓存和二级缓存?时的应答技巧和注意事项,需要的朋友参考一下 一级缓存:基于 PerpetualCache 的 HashMap 本地缓存,它的声明周期是和 SQLSession 一致的,有多个 SQLSession 或者分布式的环境中数据库操作,可能会出现脏数据。当 Session f

  • 本文向大家介绍MyBatis一二级缓存,包括了MyBatis一二级缓存的使用技巧和注意事项,需要的朋友参考一下 MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相同的查询语句,完全可以把查询结果存储起来,下次查询同样的内容的时候直接从内存中获取数据即

  • 比如使用Redis缓存了listUser的结果集,然后插入/更新/删除了数据,那怎么保证listUser的结果是最新的呢?如果说通过在插入/更新/删除操作后清空缓存,那在插入/更新/删除的操作很频繁时要如何解决呢?频繁的删缓存,那缓存的意义也就不存在了。这个问题要如何解决呢?