这是《MySQL 8.0 源码与内核实战》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 连接是 SQL 执行的入口。理解连接、线程、会话上下文和调度方式,有助于排查连接风暴、慢查询阻塞和线程资源问题。
5.1 连接路径
Client connect()
-> TCP / Unix socket
-> connection_accept
-> Connection Handler
-> create / reuse THD
-> authenticate
-> command loop
-> dispatch_command
一次连接包含:
- 网络事件;
- 线程分配;
- 会话上下文;
- 认证授权;
- 字符集协商;
- 命令循环;
- 断开清理。
5.2 THD
THD 是 Server 层最重要的会话上下文:
| 区域 | 内容 |
|---|---|
| 连接信息 | socket、客户端地址、协议 |
| 安全上下文 | 用户、host、权限 |
| 语句状态 | query、lex、command |
| 事务状态 | transaction、XA、savepoint |
| 调度状态 | killed、stage、time |
| 变量 | session variables |
| 诊断 | diagnostics area |
| 资源 | tables、MDL、临时表 |
排查时可通过 processlist 观察其外部表现:
SELECT id,user,host,db,command,time,state,info
FROM information_schema.processlist;
5.3 线程模型
传统连接模型是一个客户端连接对应一个服务线程。
Listener
-> accept connection
-> thread cache hit?
|-- yes: wake cached thread
+-- no: create thread
相关参数:
| 参数 | 说明 |
|---|---|
max_connections |
最大连接数 |
thread_cache_size |
空闲线程缓存 |
thread_handling |
线程调度模型 |
back_log |
连接等待队列 |
max_connect_errors |
错误主机限制 |
connect_timeout |
握手超时 |
线程不等于用户线程池。MySQL 企业版或 Percona 等发行版可能提供线程池插件。
5.4 命令循环
核心入口:
do_command
-> dispatch_command
-> COM_QUERY
-> mysql_parse
-> COM_STMT_PREPARE
-> mysql_stmt_prepare
-> COM_QUIT
-> close connection
断点示例:
b dispatch_command
commands
bt
c
end
可以观察 command type、包长度和会话状态。
5.5 认证与权限
handshake
-> auth plugin
-> check credentials
-> ACL cache
-> assign Security_context
相关对象:
Security_contextACL_USERLEX_USER- auth plugin
权限检查贯穿 SQL 执行,不只发生在连接时。视图、存储过程、动态 SQL 和 DEFINER 都会影响上下文。
5.6 断开与清理
连接退出时要释放:
- 打开的表;
- 元数据锁;
- 事务资源;
- 预处理语句;
- 临时表;
- 线程资源;
- 诊断信息;
- performance_schema 会话行。
如果事务未提交,连接断开会触发回滚。大事务回滚可能耗时,不能简单理解为“断开立即结束”。
5.7 连接观测
SHOW GLOBAL STATUS LIKE 'Threads_%';
SHOW GLOBAL STATUS LIKE 'Connections';
SHOW GLOBAL STATUS LIKE 'Aborted_%';
SELECT *
FROM performance_schema.threads
WHERE type='foreground';
指标含义:
| 指标 | 说明 |
|---|---|
Threads_connected |
当前连接 |
Threads_running |
正在执行命令 |
Threads_created |
累计创建线程 |
Aborted_clients |
客户端异常断开 |
Aborted_connects |
连接失败 |
Connection_errors_max_connections |
达到上限 |
5.8 连接风暴
典型现象:
Threads_connected快速上升;- CPU 用于线程创建和调度;
- 大量连接等待锁或执行 SQL;
- 应用连接池失效;
max_connections拒绝服务。
排查:
SELECT host, count(*) AS cnt
FROM information_schema.processlist
GROUP BY host
ORDER BY cnt DESC;
处理顺序:
- 识别来源;
- kill 异常会话;
- 应用限流或重启发布;
- 缩短慢查询;
- 调整连接池;
- 评估线程池;
- 拆分读写入口。
5.9 KILL 与取消
KILL query 设置 THD 的 killed 标记,执行过程中在安全点检查:
KILL QUERY
-> set killed status
-> executor / storage engine check
-> stop returning rows
-> cleanup
有些操作不能立即响应取消,例如某些 DDL 阶段、I/O、锁等待或大事务回滚。
5.10 生产注意事项
- 应用侧必须使用连接池;
- 监控
Threads_running而不只连接数; - 为管理员保留连接配额;
- 避免用超小
wait_timeout强制业务频繁重连; - 大规模连接来源要有审计;
- 云环境关注代理层连接模型;
- 变更
max_connections要同步评估内存和 CPU。
本章小结
MySQL 传统模型以连接线程为中心,THD 保存会话的语句、权限、事务和诊断上下文。连接调优要同时看网络、认证、线程、锁等待和业务连接池,避免只调大 max_connections。
思考题
THD中哪些状态会贯穿整个 SQL 生命周期?Threads_connected和Threads_running有什么区别?- 为什么连接断开后事务回滚可能继续占用资源?
KILL QUERY如何传递到执行器?- 连接风暴的处理顺序是什么?