You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决mysql-connector-java同步代码导致虚拟线程载体线程固定的问题

解决mysql-connector-java同步代码导致虚拟线程载体线程固定的问题

看了你的环境配置和栈追踪信息,问题很明确:MySQL JDBC驱动8.0.33里的同步代码块(比如ReadAheadInputStream.read和ConnectionImpl.isValid处的监视器锁)导致虚拟线程被钉住(pinned),没法释放载体线程,直接浪费了虚拟线程的伸缩性优势。下面给你几个实用的解决思路,按优先级排序:

1. 优先升级MySQL JDBC驱动版本

这是最直接有效的方案。MySQL官方在8.0.34版本开始针对虚拟线程做了专门优化,移除了多个导致虚拟线程钉住的synchronized同步块,改用更适合虚拟线程的并发控制方式(比如ReentrantLock或者无锁逻辑)。
你只需要把构建文件里的依赖版本改成8.0.34及以上就行,比如最新的稳定版8.0.36:

<!-- Maven示例 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.36</version>
</dependency>

2. 调整Hikari连接池配置,减少触发同步代码的频率

从栈追踪能看到,这次钉住是在Hikari做连接有效性校验时触发的ConnectionImpl.isValid方法。你可以通过调整Hikari的参数,降低连接校验的频率,减少进入同步块的次数:

  • 增大validationTimeout:延长连接校验的间隔时间,默认是5000毫秒,可以调到30000毫秒(30秒);
  • 调整idleTimeout和maxLifetime:减少连接的频繁创建销毁,间接减少校验次数;
  • 确保connectionTestQuery设为null:让Hikari使用JDBC4的原生isValid()方法,避免额外的查询操作。

Spring Boot的yaml配置示例:

spring:
  datasource:
    hikari:
      validation-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      connection-test-query: null

3. 尝试切换到MySQL异步驱动(适合IO密集型场景)

如果你的业务有大量数据库IO操作,可以考虑改用MySQL官方的异步JDBC驱动。异步驱动本身基于非阻塞IO设计,没有同步块导致的钉住问题,和虚拟线程的适配性更好。不过这个需要你调整代码,把同步的JDBC操作改成异步调用,适合有重构空间的项目。

4. 临时规避方案(不推荐长期使用)

如果暂时没法升级驱动或调整代码,可以通过调整JVM参数增加载体线程的数量,缓解钉住带来的阻塞问题:

-Djdk.virtualThreadScheduler.parallelism=16

这个参数会增大虚拟线程调度器的载体线程池大小(默认是CPU核心数),但只是治标不治本,没法从根源解决钉住问题,只适合临时过渡。

备注:内容来源于stack exchange,提问作者walker_fish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 09:44:32