【已解决】佬们求助,Java boy遇到一个奇怪的问题

6月3日

感谢各位佬们的热心帮助,已经找到原因所在:配置文件里有一个关于事务的配置, service 名称结尾的类文件默认开启事务,相当于 main 方法加了事务。


mybatis plus 插入一条数据之后返回 id 给另一个异步函数 asyncGet ,但是根据 id 查询数据库却是空的。

如果我在异步函数 asyncGet 中睡眠 100 毫秒就可以查询到数据。

mysql 版本是 5.7.14,数据库隔离级别是【读已提交】

  1. 没有使用主从数据库,只有一个数据库
  2. main方法没有设置事务
  3. @Async是spring boot提供的异步注解,main方法和asyncGet不在同一个类中
  4. 插入数据库后返回的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条原因并不符合:https://blog.csdn.net/jioulongzi/article/details/125329328

求助万能的佬们来看看 @Java大佬

5 个赞

@Musifei @neo @Java @javac @Javaer @JavaUser @javaisgood @javaboomBird @javagod 帮忙看看 :sob: :sob: :sob:

3 个赞

解决方案是很多,但是根因没找到,为什么sleep 100毫秒就能查询,这才是关键问题所在,求大佬不吝赐教

2 个赞

insertData(obj); 这是异步的吗

2 个赞

同步方法,这个insertData实际就是包装一个数据库对象,调用mybatis plus方法插入数据库,然后返回获取到的数据库ID

1 个赞

好的,感谢 :saluting_face: :saluting_face:,我明天去公司试试

2 个赞

公司用uuid当主键啊?

2 个赞

AIGC内容吗?文字部分请使用图片并注明,如果不是的话,我为冒犯您而抱歉

1 个赞

你礼貌的让人心疼

2 个赞

是这样的,草台班子 :joy:

2 个赞

太谨慎了,好快的叠甲

1 个赞

抱歉,我标注一下

1 个赞

@linux.dodo 国成,咱可是刀枪里滚出来的,咱可别丢份啊

3 个赞

如果是insertData(obj) 是同步操作, 那么下面的get方法就算是异步的, 应该也能直接取到, 又没有集群同步的问题

1 个赞

是事务的原因吧,你异步方法和同步方法不在同一个事务中,同步方法所在的代码块结束后才提交事务,在它提交之前你如果在异步方法中读是肯定读不到的,睡一段时间后,同步方法执行完了自然就可以读到

1 个赞

正是如此,我用mysql8.0没复现出来这个问题,所以有点懵了,公司的生产数据库我不敢瞎搞 :cry: :cry:

1 个赞

是不是数据库是集群的,然后从节点没有第一时间同步到数据?因为是异步的,然后异步读取数据又是大概率走的从库

1 个赞

始皇版规规定的绝对不允许直接出现AIGC的文字内容,三级不易,有人举报就不好了,如果非常想发出来还是费点事截图,或者注明代码由AI生成只保留代码块吧 :joy:

对哦 事务没有提交 所以异步方法第一时间没有取到值

感谢提醒,我删了吧