我正在参加「掘金·启航计划」
最近在项目中遇到了一个问题,背景如下: 数据库表中维护一个自增值,springboot项目中调用接口,去获取这个值并将这个值+1操作,短时间多次调用此接口,获取的返回值为同一个值,与数据库表中所存储的值不符,最后发现这是由于mybatis缓存引发的问题。下面来介绍一下mybatis缓存:
- 一级缓存 一级缓存是sqlsession级别的缓存 在操作数据库时,需要构造sqlsession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据 不同的sqlsession之间的缓存区域是互相不影响的。
①第一次发起查询sql查询用户id为1的用户,先去找缓存中是否有id为1的用户,如果没有,再去数据库查询用 户信息。得到用户信息,将用户信息存储到一级缓存中。
②如果sqlsession执行了commit操作(插入,更新,删除),会清空sqlsession中的一级缓存,避免脏读
③第二次发起查询id为1的用户,缓存中如果找到了,直接从缓存中获取用户信息
④mybatis默认支持并开启一级缓存。 2. 二级缓存 一级缓存因为只能在同一个SqlSession中共享,所以会存在一个问题,在分布式或者多线程的环境下,不同会话之间对于相同的数据可能会产生不同的结果,因为跨会话修改了数据是不能互相感知的,所以就有可能存在脏数据的问题,正因为一级缓存存在这种不足,所以我们需要一种作用域更大的缓存,这就是二级缓存。
- 自定义缓存
一级缓存可能存在脏读情况,那么二级缓存是否也可能存在呢? 是的,默认的二级缓存毕竟也是存储在本地缓存,所以对于微服务下是可能出现脏读的情况的,所以这时候我们可能会需要自定义缓存,比如利用redis来存储缓存,而不是存储在本地内存当中。