高并发下 MySQL Statement Cancellation Timer 的线程数暴涨

数据库 MySQL
线上业务高峰期 CPU 飙升,抓取 thread dump 发现 MySQL Statement Cancellation Timer 的线程数比较多,接收到线上预警,分析一下原因。

问题描述

线上业务高峰期 CPU 飙升,抓取 thread dump 发现 MySQL Statement Cancellation Timer 的线程数比较多,接收到线上预警,分析一下原因。业务高峰:

图片图片

下面是一些可能相关的信息( mysql 驱动,db 连接池,orm 框架)

依赖信息:

  1. mysql-jdbc 8.0.24
  2. druid 1.2.8
  3. mybatis 3.4.6

环境配置信息

  1. druid 配置,全部都是默认值
  2. mybatis 配置:
@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();
}

发生过程分析

  1. 找到该线程的创建的地方 NativeSession

图片图片

  1. 引用关系如下

图片图片

  1. 什么时候启动 enableQueryTimeouts = true

图片图片

  1. 默认值是 true

图片图片

  1. startQueryTime 的调用方 StatementImpl 的 executeQuery

图片图片

  1. 可以发现 timeOutInMillis 不为 0 的情况下,并且 enableQueryTimeouts = true 就会创建 CanalQueryTask 然后如果超时就会自动调度

方法调用如下:com.mysql.cj.CancelQueryTaskImpl#run

图片图片

处理方案

  1. 项目使用的是使用 alibaba druid

图片图片

参考:https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8调用的是 setQueryTimeOut 方法,然后传给 timeOutInMills

图片图片

如果需要取消 CancelQueryTask 需要将 validationQueryTimeout 设置为 0

  1. 并且去掉 mybatis defalutStatemnetTimeOut 参数

图片图片

  1. 如果这些都去掉可以通过 mysql  服务端 collection timeout 配置处理

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 分析工具地址:https://fastthread.io/

参考资料

  • https://segmentfault.com/a/1190000020162800
  • https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_wait_timeout
责任编辑:武晓燕 来源: 运维开发故事
相关推荐

2014-08-08 13:30:44

Nginx

2013-01-30 10:12:24

NginxNginx优化高并发

2019-10-30 16:54:08

golangredis数据库

2022-06-12 06:45:26

高并发防重

2023-02-03 15:16:42

SpringHystrix

2017-11-27 08:50:29

架构数据存储

2020-07-15 08:14:12

高并发

2019-11-08 08:40:29

Java高并发流量

2021-03-28 09:45:05

幂等性接口数据

2021-07-01 06:58:12

高并发订单号SCM

2020-09-23 22:36:27

分布式架构系统

2023-06-25 08:05:09

MySQL事务并发

2019-03-18 05:02:30

高并发京东架构

2024-02-02 11:24:00

I/O高并发场景

2021-07-29 08:13:05

高并发秒杀商品秒杀系统

2019-02-15 10:11:23

2020-04-10 10:10:28

Nginx高并发性能

2021-01-15 05:12:14

Java并发乐观锁

2018-06-29 09:06:26

高并发服务器优化

2023-10-13 08:11:22

点赞
收藏

51CTO技术栈公众号