我的一个业务在消息队列中消费数据 然后开启线程异步落库 没有执行sql语句也没有报错

问题

接受到消息队列中的消息 调用业务层方法进行消费

image-20260608135216187
image-20260608135216187

这里先查询信息再批量插入

image-20260608140313582
image-20260608140313582

在业务层中 使用mybatis-plus 批量存储数据 这个时候processMessage方法有打印相关消息信息 可以看到查询语句已经执行了 而业务层的插入sql语句并没有执行 也没有抛出异常

image-20260608140212125
image-20260608140212125

分析

经过打断点分析 可以看到传进去的数据不为空 表达式求值抛出了异常 而运行时不抛出异常

image-20260608140849786
image-20260608140849786

核心原因在于:异常是线程局部的。一个线程抛出的未捕获异常,只影响它自己,不会直接让其他已经结束的线程“复活”或重新抛出异常。

  1. 主线程启动子线程异步消费消息。
  2. 主线程继续执行,然后正常结束。
  3. 过一会儿,子线程抛出一个异常,这个异常不会导致主线程再出现任何状况,因为主线程已经不存在了
image-20260608141200603
image-20260608141200603

解决

单独捕获处理这个子线程的异常就可以看到报错信息了

image-20260608144516051
image-20260608144516051
image-20260608150713449
image-20260608150713449

问题是我继承了BaseEntity里面有mp的默认填充策略 填充了数据库中没有的字段

image-20260608150903387
image-20260608150903387

总结

子线程在执行 saveBatch 时发生了异常(如字段填充失败),但由于线程间异常隔离,主线程已结束,子线程的异常未在任何地方被捕获或记录,因此日志中无 SQL 输出,也无异常堆栈。