连接数参数 max_connections 详解
什么是 max_connections
max_connections 是 MySQL 允许的最大并发客户端连接数。默认值 151(MySQL 5.5+),实际生产环境中几乎都需要调大。
-- 查看当前值
SHOW VARIABLES LIKE 'max_connections';
-- 查看当前已使用的连接数
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
连接机制
MySQL 为每个连接分配独立的内存和线程资源:
连接到来 → MySQL 主线程收到请求
→ 分配线程(从线程池取或新建)
→ 分配会话级别的缓冲区(排序缓存、JOIN 缓存等)
→ 处理客户端请求
→ 连接关闭 → 线程放回缓存
连接相关参数
max_connections = 500 # 最大连接数(默认 151)
max_user_connections = 0 # 每个用户的最大连接数(0=不限制)
max_connect_errors = 10000 # 最大连接错误次数
connect_timeout = 10 # 连接超时秒数
wait_timeout = 600 # 非交互式连接超时
interactive_timeout = 28800 # 交互式连接超时(如 MySQL 客户端)
thread_cache_size = 100 # 线程缓存数
max_connections 的影响
设置太小
现象:
– 应用报错:Too many connections
– 正常用户无法连接数据库
– 监控告警爆发
原因:
– 应用连接池配置了太多连接
– 有慢查询导致连接长期占用
– 应用未释放连接(连接泄漏)
– 有人执行了耗时操作(备份、大查询)
设置太大
风险:
– 每个连接都要分配内存(排序缓冲区、临时表空间等)
– 大量线程竞争 CPU,上下文切换增加
– 操作系统可能达到文件句柄上限
– 内存耗尽导致操作系统 SWAP
每连接内存估算
连接所占内存的主要组成部分:
每连接 ≈ sort_buffer_size + join_buffer_size + tmp_table_size + thread_stack
默认值下:
sort_buffer_size = 256KB
join_buffer_size = 256KB
tmp_table_size = 16MB(但只在使用时分配,不是每个连接都分配)
thread_stack = 192KB
保守估算:每个活跃连接 ~1-2MB
1000 个连接 ≈ 1-2GB
注意:排序缓存和 JOIN 缓存是按连接分配但不是立即全部使用的,实际内存使用取决于连接的并发活动。但即使如此,连接数过大仍然是内存耗尽的最常见原因之一。
如何确定合适的 max_connections
方法 1:基于内存估算
-- 计算公式
max_connections = (可用内存 - 固定开销) / 每连接开销
-- 例如:服务器 8GB,Buffer Pool 用 4GB,OS 用 2GB
-- 可用内存 = 8 - 4 - 2 = 2GB
-- 每连接按 2MB 估算
-- max_connections ≈ 1024
方法 2:基于业务监控
通过 Max_used_connections 状态值来调整:
-- 查询历史最大连接数
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
-- 预留 20% 缓冲
-- 建议值 = Max_used_connections × 1.2
方法 3:基于应用连接池配置
max_connections ≥ Σ(各应用的连接池大小) + 管理连接 + 连接池增长空间
如果 3 个微服务各配置连接池 = 100
则 max_connections ≥ 300 + 10(运维连接) = 310
再加 20% 缓冲 ≈ 400
连接泄漏的排查
当 Threads_connected 持续上升但 Threads_running 很低时,很可能有连接泄漏:
-- 查看各用户的连接数
SELECT user, host, count(*)
FROM information_schema.processlist
GROUP BY user, host;
-- 查看各个 IP 的连接数
SELECT SUBSTRING_INDEX(host, ':', 1) AS ip, COUNT(*)
FROM information_schema.processlist
GROUP BY ip
ORDER BY COUNT(*) DESC;
-- 查看处于 Sleep 状态的连接
SELECT * FROM information_schema.processlist
WHERE command = 'Sleep'
AND time > 300; -- 超过 5 分钟的空闲连接
连接数用满时的紧急处理
-- 1. 查看当前运行的 SQL
SHOW FULL PROCESSLIST;
-- 2. 找出占用时间最长的连接
SELECT id, user, host, db, command, time, state, info
FROM information_schema.processlist
ORDER BY time DESC
LIMIT 10;
-- 3. 杀死长时间运行的连接(会释放该连接占用的资源)
KILL CONNECTION [connection_id];
-- 4. 临时增加连接数(不需要重启)
SET GLOBAL max_connections = 1000;
-- 5. 如果无法连接,用超级管理员权限连接
mysql -u root -p -h 127.0.0.1 --protocol=TCP
-- 或通过 socket 连接
mysql -u root -p -S /var/lib/mysql/mysql.sock
生产环境的连接管理建议
应用层
- 使用连接池:HikariCP、Druid、c3p0 等,配置合理的池大小
- 合理的池大小公式:
连接数 = ((核心数 × 2) + 有效存储数) - 设置连接超时:应用连接池的
maxLifetime< 数据库的wait_timeout - 连接验证:配置
testOnBorrow或testWhileIdle
数据库层
# 推荐配置
max_connections = 500 # 根据监控调整
max_connect_errors = 10000 # 防止错误次数过多导致 IP 被拉黑
wait_timeout = 600 # 10 分钟无活动自动断开
interactive_timeout = 7200 # 交互式连接(如 Navicat)可长一点
thread_cache_size = 100 # 缓存线程,加速新连接创建
监控告警
建议告警阈值:
- Threads_connected > max_connections × 80% → 黄色告警
- Threads_connected > max_connections × 90% → 红色告警
- Threads_running > 50 → 可能是 SQL 堆积
MySQL 8.0 的连接管理改进
MySQL 8.0 引入了:
– 资源组(Resource Groups):可以为不同优先级的连接分配不同的资源
– 连接控制插件:CONNECTION_CONTROL 插件可以限制特定 IP 的连接频率
– 更好的监控:performance_schema 提供了更细粒度的连接信息
面试常问题
Q:MySQL 报 “Too many connections” 如何处理?
A:先通过 root 用 socket 方式登录(不占 max_connections),查看 processlist 找出原因(慢查询堆积/连接泄漏/流量突增),KILL 占用高的连接,暂时扩大 max_connections,评估容量。
Q:max_connections 设置越大越好吗?
A:绝对不是。每个连接消耗内存和文件句柄,连接过多导致上下文切换频繁、内存耗尽、SWAP,反而性能断崖式下降。
Q:怎么看当前系统需要多少连接?
A:通过 Max_used_connections 看历史峰值,再留 20-30% 缓冲。同时关注 Threads_running(正在执行 SQL 的线程数),这比连接数更能反映负载。


暂无评论内容