Mybatis两次进入同一个事务,使用同样SQL语句查询获取到脏数据?
2024-06-19 17:58:43 0 举报
登录查看完整内容
Mybatis两次进入同一个事务,使用同样SQL语句查询获取到脏数据?
作者其他创作
大纲/内容
调用顺序
一个公共主方法,带Spring 默认事务隔离界别 REQUEST,调用三次SQL和参数都相同的数据查询方法,该方法为 Private
问题复现
注解形Spring 事务基于AOP实现,只能修饰public方法
需将private方法修改为public
Spring事务未生效?
测试前问题修复
方法都是private时,三次查询分别为不同的事务
方法都是public时,事务生效,三次查询共享同一个事务
Mybatis Session?
问题分析
Spring 事务
MySQL 事务
事务隔离?
Spring 事务生效
测试条件
调整 Mybatis 一级缓存类型为:session -> statement
测试方法
一级缓存生效,读到成功的数据
结果
全局调整一级缓存级别
二级缓存未生效,因为这是在同一个事务中对同一个语句进行多次操作,只走了一级缓存,没有二级缓存
关闭二级缓存
调整一级缓存类型,关闭二级缓存
localCacheScope属性设置为STATEMENT,则每次查询操作完成后,都会调用clearLocalCache()方法清空缓存。除此之外,MyBatis会在执行完任意更新语句后清空缓存
mybatis: configuration: cache-enabled: false #禁用二级缓存 local-cache-scope: statement #一级缓存指定为 statement 级别
配置文件中全局关闭 Mybatis 的一二级缓存
获取到正确的数据
全局调整一级缓存和二级缓存
事务缓存
Cache key 和 value
由 BaseExecutor 通过两个PerpetualCache类型的属性提供
一级缓存
多个命名空间可共享一个缓存
由 CachingExecutor包装类提供
二级缓存
MyBatis两级缓存示意图
区别
Mybatis 缓存?
测试
https://blog.csdn.net/qq_38966984/article/details/84729742
mybatis中使用statementType=\"STATEMENT\
其他问题
对确实是一级缓存,但是问题出在使用者对缓存数据进行了修改
Mybatis一级缓存对数据进行了干扰?
Mapper ID
偏移量
条数
具体的SQL语句及SQL语句中需要传递的所有参数
SQL 语句
所有参数值
Cache Key
执行两次查询时,只有上面的信息完全相同时,才会认为两次查询执行的是相同的SQL语句,缓存才会生效
第二次查询时没有查询数据库,打在缓存上了,而缓存中的数据是脏的?为什么会这样?Mybatis Cache Key 是通过SQL语句+Hash的方式生成的,为什么不同SQL语句查询出来的结果会混在一起?
验证后,发现 ,Mapper Example不会走前一步生成的缓存(猜测是 Mapper ID 发生了变化,所以生成的 Cache Key 不一样),而是再次查询数据,最后一步会走第一步的缓存
先使用Mybatis再使用Mybatis Mapper 再使用Mybatis,就不会影响?
发散
获取缓存引用数据发生修改,是否会直接修改缓存,Mybatis提供序列化缓存(SerializedCache),但是不确定这里是否有用上
看不对获取到的缓存值进行操作,是否会对第二次查询造成影响
com/cqsaihai/app/service/TmsToolChangeProcessService.java:815
复现
根本不是缓存主动造成,而是人操作数据时把缓存改变了
结论
https://github.com/ybqdren/bug-snippet
复现Demo
Mybatis两次进入同一个事务,使用同样SQL语句查询获取到脏数据?
0 条评论
回复 删除
下一页