追溯 MySQL Statement Cancellation Timer
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. 阅读资料
最新文章
- 【菜鸟学习jquery源码】数据缓存与data()
- leetcode 日记 3sumclosest java
- table中的标题行冻结的简单实现
- Kali Linux Web 渗透测试— 第二十课-metasploit.meterpreter
- thinkphp 3.2.3+Admin LTE后台框架
- 2D客户端+微端技术总结
- Flex-Security权限控制框架
- IOS 学习参考
- [CSS]overflow内容溢出
- MapReduce输出格式
- 学习Emacs
- netty实现消息转发服务
- RabbitMQ-从基础到实战(1)— Hello RabbitMQ
- 对lea与mov的理解
- Lucene介绍与入门使用
- 论文笔记系列-Well Begun Is Half Done:Generating High-Quality Seeds for Automatic Image Dataset Construction from Web
- 短路运算符(逻辑与&;&; 和 逻辑或||)
- 配置selenium grid
- JS的防抖,节流,柯里化和反柯里化
- day1 计算机硬件基础
热门文章
- How many integers can you find HDU - 1796 容斥原理
- MIT 6.S081 聊聊xv6的文件系统(中)日志层与事务
- 生成不带签名(BOM)的UTF8格式的XML
- centos7+腾讯云服务器搭建wordpress
- Linux命令学习-01——find -type
- H.264视频压缩标准
- ASP.NET Core 中间件(Middleware)(一)
- Android四大组件简介:Android 基础知识,开发教程
- Objective C &; Swift &; iOS &; App
- chrome device remote debug