问题描述
在线上环境,出现高并发的场景下,MySQL Statement Cancellation Timer 的线程数比较多,接收到线上预警,分析一下原因。
下图为本地模拟环境,配置比较低,问题不突出,主要是示意一下。😏😏😏
以下是 mysql 驱动,连接池,orm 框架信息
依赖信息:
环境配置信息
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setVfs(SpringBootVFS.class);
factory.setDataSource(dataSource);
//todo 省略其他配置
Configuration c = new Configuration();
c.setLogImpl(StdOutImpl.class);
c.setDefaultStatementTimeout(25000);
factory.setConfiguration(c);
return factory.getObject();
}
产生该线程分析
方法调用如下: com.mysql.cj.CancelQueryTaskImpl#run
处理方案
参考:github.com/alibaba/dru…
调用的是 setQueryTimeOut 方法,然后传给 timeOutInMills
如果需要取消 CancelQueryTask 需要将 validationQueryTimeout 设置为 0
2. 并且去掉 mybatis defalutStatemnetTimeOut 参数
- mysql 服务器会有一个参数 wait_timeout:mysql server 关闭连接之前,允许连接闲置多少秒。默认是 28800,单位秒,即 8 个小时。
# 分别查看全局、会话变量值
show global VARIABLES like '%timeout%';
show VARIABLES like '%timeout%';
- druid 可以通过 testOnBorrow 和 testOnReturn、testWhileIdle分别在链接获取,链接归还的时候判断是否有效。
复现和修复
测试代码
- 📎PushCallbackService.java
- 📎CallbackLog.java
- 📎DBTimerController.java
- 📎MccClient.java
修复效果
现象 MySQL Statement Cancellation Timer 的线程不在产生
thread dump 分析工具地址:fastthread.io/
参考资料
- segmentfault.com/a/119000002…
- dev.mysql.com/doc/refman/…