錯誤 ERROR 1040 (HY000): Too many connections 表示當前活躍連接數達到 max_connections 上限。本文系統講解連接數監控、參數調優、連接池配置、應用層洩漏排查、緊急擴容五大維度,徹底解決連接耗盡問題。
| 變量 | 含義 | 默認值 | 最大值 | 動態修改 |
|---|---|---|---|---|
max_connections | 服務器允許的最大並發連接數 | 151 (5.7+) / 100 (舊版) | 100000 (實際受 OS 文件描述符限制 ~65535) | ✅ SET GLOBAL |
threads_connected | 當前打開的連接數 (即時) | - | - | 只讀 |
max_used_connections | 啟動以來峰值並發連接數 | - | - | 只讀 |
connection_errors_max_connections | 因達上限被拒絕的連接嘗試次數 | - | - | 只讀 |
-- 1. 查看當前配置與狀態
SHOW VARIABLES LIKE 'max_connections';
SHOW GLOBAL STATUS LIKE 'threads_connected';
SHOW GLOBAL STATUS LIKE 'max_used_connections';
SHOW GLOBAL STATUS LIKE 'connection_errors_max_connections';
-- 2. 連接來源分析
SHOW PROCESSLIST;
-- 或詳細版
SELECT * FROM information_schema.PROCESSLIST ORDER BY TIME DESC;
-- 3. 按用戶/主機統計
SELECT USER, HOST, COUNT(*) AS conn_count
FROM information_schema.PROCESSLIST
GROUP BY USER, HOST
ORDER BY conn_count DESC;
SET GLOBAL max_connections = 3000;
[mysqld]
max_connections = 3000
# 相關配套調大
open_files_limit = 10000 # OS 文件描述符上限,需 ulimit -n 支援
table_open_cache = 2000 # 表緩存,防止頻繁開關表
max_user_connections = 2000 # 單用戶上限,防單點佔用
mysql soft nofile 65535
mysql hard nofile 65535
重啟 MySQL 服務生效。
| 根因類別 | 典型特徵 | 排查方法 | 解決策略 |
|---|---|---|---|
| 配置過小 | 業務增長、max_connections 仍為默認 151 | max_used_connections 接近上限、業務正常 | 調大 max_connections、配套調大 open_files_limit |
| 連接洩漏 (應用 Bug) | 連接數單調遞增、不釋放、最終耗盡 | threads_connected 持續增長、SHOW PROCESSLIST 顯示大量 Sleep 狀態、同一應用節點連接數異常 | 代碼審查:確保 try-finally/using 關閉連接、連接池 maxWait/maxIdle 配置合理 |
| 連接池配置不當 | 池大小 > max_connections、或未限制最大池尺寸 | 應用啟動後連接數迅速達上限 | 連接池 maxPoolSize ≤ max_connections / 應用實例數,預留管理連接 |
| 慢查詢堵塞 | 長事務佔用連接、新請求排隊 | SHOW PROCESSLIST 顯示大量 Time 大、State=Sending data/Locked | 優化慢 SQL、設置 max_execution_time、殺死長事務 |
| 攻擊/爬蟲 | 大量異常 IP/用戶建立連接 | PROCESSLIST 顯示大量未知來源、connection_errors_max_connections 飆升 | 防火牆限制 IP、WAF 防護、max_user_connections 限制單用戶 |
# HikariCP (Spring Boot 2+ 默認)
spring.datasource.hikari.maximum-pool-size=20 # 單實例池大小
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=300000 # 5分鐘空閒回收
spring.datasource.hikari.max-lifetime=1800000 # 30分鐘強制換新
spring.datasource.hikari.connection-timeout=30000 # 獲取連接超時 30s
spring.datasource.hikari.leak-detection-threshold=60000 # 洩漏檢測 60s
原則: 總池大小 (實例數 × maximum-pool-size) ≤ max_connections × 80% (預留 20% 給管理/備份/監控連接)。
#!/bin/bash
# 緊急將 max_connections 臨時調大至 5000
mysql -uroot -p -e "SET GLOBAL max_connections = 5000;"
# 同步調大 open_files_limit (需重啟生效,這裡僅作提醒)
echo "WARNING: open_files_limit needs restart. Current: $(mysql -uroot -p -e 'SHOW VARIABLES LIKE \"open_files_limit\";' -sN | awk '{print $2}')"
# 觀察 10 分鐘
sleep 600
# 恢復原值 (視情況)
# mysql -uroot -p -e "SET GLOBAL max_connections = 3000;"
Too many connections 不是病,是症狀。 核心動作三步走:
max_used_connections 日峰值,配置 max_connections = 峰值 × 1.5~2。pt-query-digest 分析慢日誌,優化 Top 10 慢 SQL,釋放被堵塞的連接。建立連接數告警規則 (threads_connected / max_connections > 80% 觸發),配合自動擴容腳本,實現從「救火」到「防火」的轉變。