遊戲 Lag 白皮書 › L12 資料庫
連線池耗盡 Connection pool exhaustion
原因 ID db-pool · 主要負責 遊戲開發團隊(伺服器開發) · 協同 基礎設施團隊(DB 基礎設施)
在含圖解與實驗的完整版中開啟卡片 →
與 DB 建立的連線數是固定的,慢查詢占住連線時,其餘請求只能等待。
為什麼 慢查詢或請求暴增,使所有連線都在使用中 → 於是 新請求要等到有連線空出來 → 畫面上 登入時無限讀取、存檔變慢、逾時
- 症狀
- 連不上/無限讀取, 輸入延遲
- 因素
- 停滯, 延遲
- 誰會遇到
- 整個伺服器, 只有特定功能
- 何時
- 剛登入/維護剛結束, 人潮湧入時
- 負責單位
- 主要負責 遊戲開發團隊(伺服器開發) · 協同 基礎設施團隊(DB 基礎設施)
- 遊戲開發團隊要做的事
- 消除慢查詢、調整連線池大小與等待逾時(不要一味加大連線池)、依功能拆分連線池。
- 基礎設施團隊要做的事
- 確認 DB 的最大連線數與 CPU、IOPS 餘裕;擴充伺服器或自動擴展前,確認伺服器數 × 連線池大小在最大連線數以內;把連線等待與鎖等待指標加入監控。
- 數值參考
- 需要的連線數可用「每秒請求數 × 每筆請求占用連線的時間」估算。每秒 2,000 筆、每筆 5ms 時,平均隨時有 10 條連線在忙。考量請求湧入的情況,通常會準備兩三倍。查詢變慢到 150ms 時,同樣的請求量就需要 300 條。
- 圖表上
- 碰到上限後持平 · 使用中的 DB 連線數、連線等待時間
- 查看位置
- 在 DB 端依遊戲伺服器統計連線狀態。MySQL 看 SHOW PROCESSLIST 的 Host、Command(閒置連線為 Sleep)、Time,以及 Threads_connected、Threads_running 與被拒絕的連線數 Connection_errors_max_connections。PostgreSQL 把 pg_stat_activity 依 client_addr、state 分組統計。遊戲伺服器的連線池函式庫有輸出等待數與等待時間時,一併查看
- 符合的跡象
- 某台遊戲伺服器的連線達到連線池大小且全部都在執行查詢、閒置連線為 0 的期間,登入與存檔都在等待。或是 DB 的總連線數碰到 max_connections,新連線被拒絕
- 不符合的跡象
- 閒置連線充足卻仍然很慢時,是查詢本身的延遲(db-no-index、db-hot-row)或 DB 資源飽和的問題
- 確認方式
- 用基礎設施工具確認(不需要遊戲程式碼)
- 深入了解
- 一味加大連線池,只會增加 DB 的 CPU 負載與鎖定競爭,讓所有人一起變慢。此外,伺服器數 × 連線池大小超過 DB 的最大連線數時,新增或重新啟動的伺服器甚至無法建立連線。這在自動擴展或維護剛結束時很常見。
出處
- Number Of Database Connections PostgreSQL
DB 資源用盡之後,增加連線反而會降低處理量;讓活躍連線數配合資源、其餘放進佇列,延遲與處理量都會比較好 - Too many connections MySQL
max_connections 全部用完時,新連線會因 Too many connections 錯誤被拒絕 - Connections and Authentication (PostgreSQL Documentation) PostgreSQL
max_connections:同時連線數上限,預設通常為 100 - SHOW PROCESSLIST Statement MySQL
Host(用戶端位址)、Command(閒置 session 為 Sleep)、Time、State - Server Status Variables MySQL
Threads_connected、Threads_running、Connection_errors_max_connections(因達到 max_connections 而被拒絕的連線數) - The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
pg_stat_activity:每條連線的 client_addr 與 state(active、idle、idle in transaction 等)
相關原因
同一層:L12 資料庫
同一症狀(連不上/無限讀取)在其他層的原因
查看含圖解與實驗的完整版卡片