timeless
(timeless)
1
6月3日
感谢各位佬们的热心帮助,已经找到原因所在:配置文件里有一个关于事务的配置, service 名称结尾的类文件默认开启事务,相当于 main 方法加了事务。
mybatis plus 插入一条数据之后返回 id 给另一个异步函数 asyncGet ,但是根据 id 查询数据库却是空的。
如果我在异步函数 asyncGet 中睡眠 100 毫秒就可以查询到数据。
mysql 版本是 5.7.14,数据库隔离级别是【读已提交】
- 没有使用主从数据库,只有一个数据库
- main方法没有设置事务
- @Async是spring boot提供的异步注解,main方法和asyncGet不在同一个类中
- 插入数据库后返回的id是uuid,用的是mybaits plus提供的@Table注解
public void main() {
// 数据库插入一条数据
String id = insertData(obj);
// 另一个类的异步方法
asyncGet(id);
}
@Async
public void asyncGet(String id) {
// 根据ID查询数据库,结果是null
select(id);
// 如果查询之前sleep 100ms就可以查询成功
sleep(100);
select(id);
}
我谷歌了一下,有一篇CSDN的博客记录了类似的现象,但列举的3条原因并不符合:Spring新增数据后立即查询,但是查询不到#Mybatis新增数据丢失_mybatis添加完数据,立即查询怎么查询不到?-CSDN博客
求助万能的佬们来看看 @Java大佬
4 个赞
timeless
(timeless)
2
3 个赞
timeless
(timeless)
4
解决方案是很多,但是根因没找到,为什么sleep 100毫秒就能查询,这才是关键问题所在,求大佬不吝赐教
2 个赞
timeless
(timeless)
7
同步方法,这个insertData实际就是包装一个数据库对象,调用mybatis plus方法插入数据库,然后返回获取到的数据库ID
1 个赞
AIGC内容吗?文字部分请使用图片并注明,如果不是的话,我为冒犯您而抱歉
1 个赞
@linux.dodo 国成,咱可是刀枪里滚出来的,咱可别丢份啊
3 个赞
如果是insertData(obj) 是同步操作, 那么下面的get方法就算是异步的, 应该也能直接取到, 又没有集群同步的问题
1 个赞
weirrn
(weirrn)
18
是事务的原因吧,你异步方法和同步方法不在同一个事务中,同步方法所在的代码块结束后才提交事务,在它提交之前你如果在异步方法中读是肯定读不到的,睡一段时间后,同步方法执行完了自然就可以读到
1 个赞
timeless
(timeless)
19
正是如此,我用mysql8.0没复现出来这个问题,所以有点懵了,公司的生产数据库我不敢瞎搞

1 个赞
user46
(IBM)
20
是不是数据库是集群的,然后从节点没有第一时间同步到数据?因为是异步的,然后异步读取数据又是大概率走的从库
1 个赞
始皇版规规定的绝对不允许直接出现AIGC的文字内容,三级不易,有人举报就不好了,如果非常想发出来还是费点事截图,或者注明代码由AI生成只保留代码块吧 
对哦 事务没有提交 所以异步方法第一时间没有取到值