首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 「Too many connections」 錯誤徹底解決方案:從參數調優到連接池治理

     編輯:MySQL 綜合教學

錯誤現象

ERROR 1040 (HY000): Too many connections

應用日誌大量拋出數據庫連接失敗異常,業務請求超時或報 500。

核心指標與關係

指標含義默認值理論上限
max_connections 服務端允許的最大並發連接數 151 (MySQL 5.7+) 16384
threads_connected 當前已建立的連接數(含睡眠連接) 動態變化 ≤ max_connections
Threads_running 當前正在執行查詢的線程數 動態變化 ≤ threads_connected

觸發條件:threads_connected == max_connections 時,新連接請求被拒絕。

快速排查步驟

  1. 查看當前配置:
    mysql> SHOW VARIABLES LIKE 'max_connections';
    +-----------------+-------+
    | Variable_name   | Value |
    +-----------------+-------+
    | max_connections | 151   |
    +-----------------+-------+
    
  2. 監控實時連接數:
    mysql> SHOW STATUS LIKE 'Threads_connected';
    +-------------------+-------+
    | Variable_name     | Value |
    +-------------------+-------+
    | Threads_connected | 151   |
    +-------------------+-------+
    
    或持續監控:watch -n 1 'mysql -e "SHOW STATUS LIKE \"Threads_connected\""'
  3. 定位連接來源:
    mysql> SELECT host, user, COUNT(*) AS cnt, 
                  SUM(IF(command='Sleep',1,0)) AS sleep_cnt
           FROM information_schema.processlist
           GROUP BY host, user
           ORDER BY cnt DESC;
    
    重點關注 Sleep 佔比高的客戶端 IP,通常為連接泄漏或連接池配置不當。

常見根因與對應對策

1. max_connections 設置過小

現象:業務增長導致並發超過默認 151。

對策:修改配置文件 my.cnf:

[mysqld]
max_connections = 3000   # 根據機器內存與業務峰值評估,建議不超過 8000

重啟生效。注意:每個連接約消耗 256KB-2MB 內存(取決於 sort_buffer_size、join_buffer_size 等),3000 連接約需 1-4GB 額外內存,確保機器內存充足。

2. 應用連接池洩漏 / 未釋放

現象:Sleep 連接佔比 > 80%,且隨時間單調增長。

對策:

  • 檢查代碼:確保 try-with-resources / finally 中關閉 Connection、Statement、ResultSet。
  • 連接池設置 validationQuery + testOnBorrow / testWhileIdle,配合 timeBetweenEvictionRunsMillis 定期清理空閒連接。
  • 設置合理的 maxIdle、minIdle、maxWait,避免池無限增長。

3. 長事務 / 慢查詢佔用連接

現象:Threads_running 持續偏高,SHOW PROCESSLIST 顯示大量 Time 較大的查詢。

對策:

  • 優化慢 SQL(加索引、拆分大事務、避免全表掃描)。
  • 設置 innodb_lock_wait_timeout、net_read_timeout、net_write_timeout 防止連接長期阻塞。
  • 啟用 performance_schema 或 sys schema 監控事務執行時間,超時自動殺死。

4. 連接風暴(突發流量)

現象:秒殺、定時任務並發啟動導致瞬間連接數飆升。

對策:

  • 應用層限流(令牌桶/漏桶),平滑流量峰值。
  • 使用 ProxySQL / MyCat 等中間件做連接複用與排隊。
  • 設置 max_connections 較大值 + back_log 增大(如 2000),緩衝瞬間衝擊。

5. 系統級文件描述符限制

現象:即使調大 max_connections,連接數仍卡在 1024 或 4096。

對策:

# /etc/security/limits.conf
mysql soft nofile 65535
mysql hard nofile 65535

# /etc/sysctl.conf
fs.file-max = 1000000

重啟 MySQL 服務生效。

生產環境推薦配置模板

[mysqld]
# 連接數
max_connections = 5000
back_log = 2000

# 連接超時清理
wait_timeout = 28800          # 8小時無活動斷開
interactive_timeout = 28800
net_read_timeout = 30
net_write_timeout = 60

# 緩衝區控制(減少單連接內存佔用)
sort_buffer_size = 256K
join_buffer_size = 256K
read_buffer_size = 128K
read_rnd_buffer_size = 256K

# 安全
max_connect_errors = 100000
skip_name_resolve = 1

監控告警建議

  • 告警閾值:Threads_connected / max_connections > 80% 觸發預警,> 95% 觸發嚴重告警。
  • 關鍵儀表盤:Grafana + Prometheus (mysqld_exporter) 監控 mysql_global_status_threads_connected、mysql_global_variables_max_connections、mysql_global_status_threads_running、mysql_global_status_aborted_connects。
  • 自動化巡檢:每日統計連接數峰值趨勢,配合容量規劃提前擴容。

總結

「Too many connections」 絕非單純調大 max_connections 即可解決,需建立 「配置調優 + 連接池治理 + SQL優化 + 限流熔斷 + 監控告警」 的全鏈路治理體系。優先排查連接泄漏與慢查詢,再評估是否真需要擴大 max_connections,避免因內存不足導致 OOM Killer 殺死 MySQL 進程,造成更嚴重的服務不可用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved