原文

1. 背景

在 jstack 的内容中可以看到以下的 MySQL Statement Cancellation Timer 守护线程, 在业务高峰期的时候会出现大量的这类守护线程, 由此追溯该线程的生命周期过程;

"MySQL Statement Cancellation Timer" #20647 daemon prio=5 os_prio=0 tid=0x00007f2d087e9800 nid=0xfb83 in Object.wait() [0x00007f2b4b45a000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.util.TimerThread.mainLoop(Timer.java:552)
- locked <0x00000005da147038> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505) Locked ownable synchronizers:
- None "MySQL Statement Cancellation Timer" #24138 daemon prio=5 os_prio=0 tid=0x00007f402802c800 nid=0x4cf64 in Object.wait() [0x00007f3e49453000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.util.TimerThread.mainLoop(Timer.java:526)
- locked <0x00000005f606cc60> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505) Locked ownable synchronizers:
- None

2. TimerThread

java.util.TimerThread 是 Timer.java 文件里的一个内部类, 主要负责 Timer 队列任务的执行和调度;

  • 根据定位 Timer.java:526 位置的代码, 当前状态 WAITING (on object monitor), 表示当前的 timer 线程池为空, 正在等待新入驻;
  • 根据定位 Timer.java:552 位置的代码, 当前状态 TIMED_WAITING (on object monitor) 表示任务等待被激活;

3. getCancelTimer

根据线程名称 MySQL Statement Cancellation Timer 继续追溯, 在 com.mysql.jdbc.ConnectionImpl#getCancelTimer 方法中找到该 TimerThread 的创建(cancelTimer):

4. getCancelTimer 的上游调用

主要是 mysql-connector-java-xxx.jar 中负责 sql 查询的 Statement

5. 创建 CancelTask timeoutTask

在 com.mysql.jdbc.StatementImpl#executeQuery 方法中可以发现, 当启用 queryTimeout 且 timeoutInMillis!=0 时, 在执行 sql 的时候就会创建一个 CancelTask 的线程来控制超时; (后面那个 versionMeetsMinimum 是个版本判断可以先忽略)

然后在项目的 application.yml 中发现配置 mybatis.configuration.default-statement-timeout: 5, 所以 mybatis 在每次的数据库查询都会加上 queryTimeout, 且该配置对全局 SQL 生效, 包括 insert, select, update;

6. CancelTask 执行过程

在 com.mysql.jdbc.StatementImpl.CancelTask#run 方法中, 会另起一个线程, 判断如果启用了 queryTimeoutKillsConnection 的配置时, 会调用当前 Statement 对应的 Connection 里的 realClose 方法;

在 realClose 方法里发现会关闭 cancelTimer 线程;

7. Connection 关闭时

在 com.mysql.jdbc.ConnectionImpl#close 方法里也会发现有 realClose 方法的调用, 即在连接关闭时也会处理 cancelTimer 的释放

8. 总结 MySQL Statement Cancellation Timer 线程的流程

设置了 queryTimeout 会使 jdbc driver 在每次查询数据库时新建 CancelTask(timeoutTask对象) 线程来处理超时, 并使用 CancelTimer(在 ConnectionImpl类中) 来进行调度;

如果 SQL 查询超时了, 则会在 timeoutTask 的 run 方法里调用 com.mysql.jdbc.ConnectionImpl#realClose 来释放 CancelTimer;

如果 Connection 正常关闭 close 时, 也会调用 com.mysql.jdbc.ConnectionImpl#realClose 来释放 CancelTimer;

9. 阅读资料

  1. 一次数据库连接池优化的实践剖析
  2. MySQL Statement Cancellation Timer问题

追溯 MySQL Statement Cancellation Timer的更多相关文章

  1. MYSQL Statement violates GTID consistency: Updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as

    [2019-04-21 10:17:20] [ERROR] [org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144] Statement viola ...

  2. mysql Statement violates GTID consistency 的坑

    今天项目迁移,重新换了一个数据库版本,然后问题来了,原本运行正常的程序迁移过来之后就是不能正常运行,后台报错如下: update tbl_user_info set -- 强制下架 mv_count ...

  3. MYSQL Statement violates GTID consistency: CREATE TABLE ... SELECT. 错误代码: 1786 问题

    1.在MYSQL中,执行建表语句时CREATE TABLE  aaaa  AS SELECT * FROM menu;  报: 错误代码: 1786Statement violates GTID co ...

  4. MySQL Fabric和MyBatis的整合过程中遇到的问题

    这是我昨天在整合MySQL Fabric和MyBatis时遇到的问题,花了大半天才解决的问题,解决的过程中在网上查找了很久,都没有找到解决的方案.现在记下来,希望能够帮助有同样问题的朋友.如果各位朋友 ...

  5. registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped.

    最近在用maven整合SSH做个人主页时候,在eclipse里面使用tomcat7插件发布项目是没有问题的,但当打包成war之后,使用tomcat7单独发布项目,就出现了以下的错误. 严重: Cont ...

  6. jstack工具查看系统线程问题

    背景: 最近在做项目系统的异常测试,项目依赖于nkv,需要模拟依赖组件nkv异常时系统的响应及性能情况.通过tc工具模拟当服务器发送到nkv的请求超时时系统的响应.发现接口返回错误率100%,查看服务 ...

  7. JDBC驱动自身问题引发的FullGC

    公众号HelloJava刊出一篇<MySQL Statement cancellation timer 故障排查分享>,作者的某服务的线上机器报 502(502是 nginx 做后端健康检 ...

  8. Tomcat6.0的Thisisverylikelytocreateamemoryleak异常

    從Apache Tomcat 5.5升級到6.0,通常不用太大的修改,原有的Web Application就能繼續運作.不過在server.xml中設定MySQL Datasource,卻出現一串惱人 ...

  9. Tomcat常见内存溢出的解决办法

    PermGen space错误解决方法 在看下文之前,首先要确认意见事情,就是你是如何启动tomcat的,我们在平时的开发环境当中,都是通过startup.bat方式启动tomcat的,那么你按照下面 ...

随机推荐

  1. 1006 How many?

    Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 36   Accepted: 2 Description 有一天,小Q给了小J ...

  2. Acwing 154 滑动窗口(单调队列)经典模板

    给定一个大小为n≤106n≤106的数组. 有一个大小为k的滑动窗口,它从数组的最左边移动到最右边. 您只能在窗口中看到k个数字. 每次滑动窗口向右移动一个位置. 以下是一个例子: 该数组为[1 3 ...

  3. 前端模块化之ES Module

    一.概述 之前提到的几种模块化规范:CommonJS.AMD.CMD都是社区提出的.ES 2015在语言层面上实现了模块功能,且实现简单,可以替代CommonJS和AMD规范,成为在服务器和浏览器通用 ...

  4. HTTP 请求过程以及报文结构

    目录 HTTP 请求流程 HTTP 请求报文 请求行 方法字段(Request Method) URL字段(Uniform Resource Locator) HTTP 协议版本字段(略) 请求/响应 ...

  5. Kubernets二进制安装(10)之部署主控节点部署调度器服务kube-scheduler

    Kubernetes Scheduler是一个策略丰富.拓扑感知.工作负载特定的功能,调度器显著影响可用性.性能和容量.调度器需要考虑个人和集体的资源要求.服务质量要求.硬件/软件/政策约束.亲和力和 ...

  6. Linux内核4.19.1编译

    linux内核编译 1.1 大致步骤 下载linux内核4.19.1 官网链接: https://www.kernel.org/ 官网下载经常速度太慢,无法下载,提供另一个链接: http://ftp ...

  7. python yield && scrapy yield

    title: python yield && scrapy yield date: 2020-03-17 16:00:00 categories: python tags: 语法 yi ...

  8. HDU 4336 Card Collector(状压 + 概率DP 期望)题解

    题意:每包干脆面可能开出卡或者什么都没有,一共n种卡,每种卡每包爆率pi,问收齐n种卡的期望 思路:期望求解公式为:$E(x) = \sum_{i=1}^{k}pi * xi + (1 - \sum_ ...

  9. [USACO15JAN]Moovie Mooving G

    [USACO15JAN]Moovie Mooving G 状压难题.不过也好理解. 首先我们根据题意: she does not want to ever visit the same movie t ...

  10. Monorepo All In One

    Monorepo All In One monorepos 只是一种思想,或设计模式,架构风格 https://trunkbaseddevelopment.com/monorepos/ Lerna h ...