從查詢到配置:線上排查與調(diào)優(yōu)實戰(zhàn)指南)
接手過線上MySQL的人多半都經(jīng)歷過那種“數(shù)據(jù)庫突然連不上了”的瞬間。應(yīng)用日志里刷著一排Too many connectionsDBA群里瞬間炸鍋第一反應(yīng)就是敲show variables like max_connections看上限再敲show status like Threads_connected看當(dāng)前占用。這套動作我做過無數(shù)次但老實說早期我對連接數(shù)的理解也就停留在“滿了就調(diào)大”這個層面直到被幾次故障教育之后才真正把連接數(shù)的查詢、配置、監(jiān)控和治理串成一條線。這篇就把MySQL連接數(shù)從查看到配置、從參數(shù)到實戰(zhàn)的完整脈絡(luò)梳理一遍全是踩過坑之后沉淀下來的東西。1. 先搞懂連接數(shù)到底是怎么回事1.1 連接的本質(zhì)和開銷MySQL的“連接數(shù)”本質(zhì)上是客戶端與服務(wù)端之間建立的會話數(shù)量。每一次連接服務(wù)端都要為它分配線程、內(nèi)存、臨時資源連接建立時還要經(jīng)歷TCP握手、認證、權(quán)限校驗這一整套流程。你可以把每個連接想象成餐廳里的一把椅子——椅子數(shù)量有限每個客人坐下來都要占地方服務(wù)員線程要招呼他后廚存儲引擎要為他備菜??腿俗吡艘巫硬拍芸粘鰜淼巫颖旧聿粫约鹤兌唷_@個類比解釋了為什么連接數(shù)不是可以無限漲的。每個連接占用的內(nèi)存通常在幾百KB到幾MB之間取決于會話級變量、排序緩沖區(qū)、臨時表內(nèi)存等配置。如果有幾百個連接同時存在光會話內(nèi)存就是一筆不小的開銷。更重要的是MySQL的線程調(diào)度能力有限連接數(shù)堆積到一定程度CPU會大量消耗在線程切換上導(dǎo)致整體吞吐下降——這時候數(shù)據(jù)庫不是“滿”了而是“癱”了。1.2 連接被誰占用了排查連接數(shù)問題的第一步不是看總數(shù)而是看構(gòu)成。一個典型的MySQL實例上連接主要來自幾個方向應(yīng)用連接池絕大多數(shù)連接來自業(yè)務(wù)側(cè)。Java應(yīng)用里常見的連接池如Druid、HikariCP每個實例會維護一組連接微服務(wù)規(guī)模一大連接數(shù)自然水漲船高。監(jiān)控腳本和定時任務(wù)很多人會忽略這些。監(jiān)控采集、報表任務(wù)、批量腳本如果寫在循環(huán)里每次new一個連接又沒釋放連接數(shù)會被慢慢“吃”掉。管理端和手工查詢Navicat、Workbench這類GUI工具每個打開的查詢窗口對應(yīng)一個連接。開發(fā)環(huán)境人手一把看起來不多但疊加起來也可能占掉幾十個連接。閑置連接這是最陰險的占用。應(yīng)用獲取連接后忘了歸還或者連接池最小空閑數(shù)配置過高大量連接處于Sleep狀態(tài)既不干活也不釋放。分類清楚了才能對癥下藥。這也是為什么我們查連接數(shù)時永遠要追問一句“這些連接都是誰”。1.3 連接上限從哪來MySQL對連接數(shù)的限制最直接的是max_connections參數(shù)。它控制的是整個實例允許同時存在的客戶端連接總數(shù)包括所有庫、所有用戶。除此之外還有一個max_user_connections單獨限制單個賬號的最大連接數(shù)默認是0也就是不限制。值得說明的是max_connections是實例級別的硬上限但“生效”的方式不是寫死而是動態(tài)判斷當(dāng)已有連接數(shù)達到上限后再來的新連接請求會直接被拒絕錯誤碼是ER_CON_COUNT_ERROR也就是我們熟悉的Too many connections。生產(chǎn)環(huán)境最常見的誤區(qū)是把max_connections當(dāng)成一個需要“夠用就行”的配置結(jié)果上線時夠用業(yè)務(wù)一漲直接被打穿。正確做法是按最壞情況估算同時留出緩沖余量。2. 查詢連接數(shù)從命令行到SQL的全套姿勢2.1 第一件事先看全局狀態(tài)最基礎(chǔ)也是最高頻的查詢命令是這兩條SHOW VARIABLES LIKE max_connections; SHOW STATUS LIKE Threads_connected;SHOW VARIABLES查的是配置值SHOW STATUS查的是實時狀態(tài)。Threads_connected表示當(dāng)前已建立的連接數(shù)這兩個值一比就能看出連接水位。比如配置上限是500當(dāng)前已經(jīng)480那就得警惕了。除了Threads_connected還有幾個狀態(tài)值值得一起看SHOW STATUS LIKE Threads_running; SHOW STATUS LIKE Threads_created; SHOW STATUS LIKE Aborted_connects; SHOW STATUS LIKE Connection_errors_max_connections;Threads_running當(dāng)前正在執(zhí)行的連接數(shù)。這個值最能反映數(shù)據(jù)庫真實壓力。連接數(shù)高不一定有問題但Threads_running持續(xù)走高說明SQL真的在跑要關(guān)注慢查詢和鎖等待。Threads_created為處理連接而創(chuàng)建的線程數(shù)。如果這個值在持續(xù)快速增加說明系統(tǒng)在頻繁創(chuàng)建線程通常意味著連接在頻繁建立和斷開——連接池沒用好。Aborted_connects連接建立失敗的次數(shù)可以用來判斷是否有連接被拒。Connection_errors_max_connections因為達到max_connections上限而被拒絕的連接次數(shù)。這個值只要大于0就說明被拒過。2.2 查當(dāng)前活躍連接information_schema 三板斧全局狀態(tài)只能看到總數(shù)想知道“誰占著連接”得上information_schema.processlistSELECT id, user, host, db, command, time, state, info FROM information_schema.processlist ORDER BY time DESC;這個查詢會列出所有當(dāng)前連接重點看幾列commandSleep表示空閑連接Query表示正在執(zhí)行查詢Connect表示正在建立連接。time當(dāng)前狀態(tài)持續(xù)的時間。某個Query的 time 特別大基本就是慢查詢或者鎖等待。state執(zhí)行狀態(tài)比如Sending data、Waiting for table metadata lock、Locked不同狀態(tài)對應(yīng)不同問題。info正在執(zhí)行的SQL語句不過只有CommandQuery時才有內(nèi)容。排查連接數(shù)異常我通常先跑這個SQL把結(jié)果按command分組統(tǒng)計再按host分組看來源SELECT command, COUNT(*) AS cnt FROM information_schema.processlist GROUP BY command; SELECT host, COUNT(*) AS cnt FROM information_schema.processlist GROUP BY host ORDER BY cnt DESC;這兩刀下去大頭在哪基本就清楚了全是Sleep那就是連接池沒回收集中在某個host那就是那個應(yīng)用實例有問題全是Query且 time 很大那就不用管連接數(shù)了先查SQL吧。2.3 performance_schema 更細的視角information_schema.processlist在連接數(shù)非常多比如上千或者大量被占用時查詢本身會有些開銷而且只能看到當(dāng)前瞬間的狀態(tài)。如果要做歷史趨勢分析或者更細維度的統(tǒng)計用performance_schema更合適。SELECT EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT FROM performance_schema.events_statements_summary_by_digest ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;這個用來定位消耗最多的SQL模式。連接數(shù)的場景下更常用的是看performance_schema.threadsSELECT TYPE, PROCESSLIST_COMMAND, COUNT(*) AS cnt FROM performance_schema.threads GROUP BY TYPE, PROCESSLIST_COMMAND;performance_schema.threads會包含后臺線程和前臺連接線程能更精確地區(qū)分哪些是系統(tǒng)內(nèi)部線程哪些是真實客戶端連接。不過說實話日常排查我還是優(yōu)先用information_schema.processlist它直觀、覆蓋面夠用。performance_schema更適合做監(jiān)控采集和深度分析因為它的歷史累計數(shù)據(jù)是現(xiàn)成的不用自己額外記錄。2.4 把連接狀態(tài)做成監(jiān)控手工查只能解決“當(dāng)時發(fā)生了什么”生產(chǎn)環(huán)境更需要的是“連接數(shù)趨勢”。我比較推薦的做法是把核心指標(biāo)接入監(jiān)控系統(tǒng)至少采集這幾個值max_connections配置上限變更時要同步更新監(jiān)控里的閾值。Threads_connected當(dāng)前連接數(shù)按百分比設(shè)置告警閾值。比如達到上限的80%告警達到90%緊急告警。Threads_running當(dāng)前執(zhí)行連接數(shù)這個值超過幾十就要警惕SQL性能問題了。Aborted_connects增量異常時說明連接被拒絕過。采集方式可以直接用SHOW GLOBAL STATUS輪詢也可以用performance_schema的表。之前我見過一個坑監(jiān)控腳本自身也使用了數(shù)據(jù)庫連接去采集狀態(tài)結(jié)果數(shù)據(jù)庫連接打滿時監(jiān)控反而連不上采集任務(wù)失敗告警沒發(fā)出來。后來我們把監(jiān)控采集改成直連本地socket并單獨留一條管理通道才徹底避免了這個尷尬。3. 配置連接數(shù)參數(shù)詳解與調(diào)優(yōu)思路3.1 max_connections 到底該設(shè)多大關(guān)于max_connections網(wǎng)上流傳著“設(shè)個1000、2000就完事”的說法這是典型的頭疼醫(yī)頭。連接數(shù)上限不是拍腦袋定的要結(jié)合三個因素算因素一是內(nèi)存。每個連接至少會占用thread_stack加net_buffer_length等固定開銷但真正的大頭是會話級的排序緩沖、臨時表、join緩沖等。粗略估算時可以按每個連接1MB到2MB來算。假設(shè)實例內(nèi)存32GB預(yù)留一半給InnoDB緩沖池和操作系統(tǒng)剩下16GB給連接那理論上可以支持8000到16000個連接。但這只是內(nèi)存約束不是推薦值。因素二是CPU。每個連接的活躍查詢都會消耗CPU。一個4核8線程的實例同時能高效運行的查詢也就十幾個。就算連接數(shù)堆到幾千絕大多數(shù)連接也只能排隊等CPU數(shù)據(jù)庫的TPS不會因此提高反而線程切換開銷會把性能拖垮。因素三是業(yè)務(wù)形態(tài)。max_connections 預(yù)估活躍連接峰值 緩沖余量比如一個應(yīng)用實例連接池配置20個連接總共50個實例那理論上限是1000再加上監(jiān)控、管理、備用流量建議設(shè)到1200。注意這里說的是“連接池配置的總額”不是當(dāng)前實際活躍連接數(shù)——因為連接池一般會維持比活躍請求更多的空閑連接。我見過一份配置調(diào)優(yōu)記錄某電商系統(tǒng)在促銷前把max_connections從500調(diào)到2000結(jié)果促銷還沒開始數(shù)據(jù)庫先卡死了。原因就是連接數(shù)上來了但每連接的內(nèi)存和CPU開銷也上來了系統(tǒng)資源根本扛不住。后來把連接池最大值壓下去配合排隊機制系統(tǒng)反而穩(wěn)定了。這就是典型的“連接數(shù)配置不是開得越大越好”。3.2 連接生命周期wait_timeout 與 interactive_timeout連接數(shù)為什么會越積越多很多時候不是應(yīng)用故意不釋放而是連接變成了“僵尸連接”——既沒關(guān)閉也不干活就那么一直躺著。控制這個現(xiàn)象的關(guān)鍵參數(shù)是wait_timeout和interactive_timeout。SHOW VARIABLES LIKE wait_timeout; SHOW VARIABLES LIKE interactive_timeout;wait_timeout非交互式連接的空閑超時時間默認28800秒8小時。interactive_timeout交互式連接的空閑超時時間同樣默認28800秒。這個默認值在云上環(huán)境經(jīng)常成為“連接數(shù)泄漏”的幫兇。應(yīng)用獲取連接后不歸還連接池又不主動踢掉連接就會一直占著。8小時后才能被服務(wù)端強制斷開——這個節(jié)奏太慢了。建議線上把wait_timeout調(diào)小比如600秒10分鐘甚至300秒5分鐘。但對交互式連接不要一刀切因為DBA自己用命令行連上去可能掛著看個長查詢這時候interactive_timeout需要保持足夠長。這里有個容易踩的坑修改wait_timeout只對之后新建的連接生效不是的這個參數(shù)對已存在的連接立即生效MySQL會周期性檢測空閑連接并強制斷開。但也正因如此如果連接池里的連接在空閑狀態(tài)被服務(wù)端切掉了應(yīng)用連接池如果沒有做好連接有效性檢測第一次使用這個連接時會拋異常走一次重連流程業(yè)務(wù)上表現(xiàn)為偶發(fā)報錯。所以調(diào)wait_timeout時一定要確認應(yīng)用連接池的testOnBorrow或validationQuery是開著的。3.3 連接回收與復(fù)用thread_cache_size每次新建連接MySQL都要創(chuàng)建一個線程連接斷開時線程也要銷毀。頻繁創(chuàng)建銷毀線程是有成本的。thread_cache_size就是用來緩存空閑線程的作用類似連接復(fù)用加速器。SHOW VARIABLES LIKE thread_cache_size;這個參數(shù)的值表示MySQL可以緩存多少個空閑線程用于復(fù)用。設(shè)置多大合適可以看狀態(tài)值SHOW STATUS LIKE Threads_created; SHOW STATUS LIKE Connections;Threads_created除以Connections可以得到線程創(chuàng)建率。如果這個比例很低說明大部分連接都在復(fù)用已有線程thread_cache_size夠用如果比例偏高說明線程頻繁創(chuàng)建銷毀可以適當(dāng)調(diào)大thread_cache_size。不過要強調(diào)一點thread_cache_size治標(biāo)不治本。如果連接在頻繁創(chuàng)建和銷毀真正的問題通常是應(yīng)用連接池參數(shù)不合理——比如連接池最大生命周期太短、空閑回收太激進。這個參數(shù)只能緩解癥狀不該把它當(dāng)成主力優(yōu)化手段。3.4 連接數(shù)與連接池的聯(lián)動配置前面說的都是MySQL服務(wù)端的參數(shù)但線上連接數(shù)問題的根源往往不在服務(wù)端而在應(yīng)用側(cè)的連接池配置。這里把兩邊的指標(biāo)對應(yīng)起來看連接池參數(shù)作用與MySQL的對應(yīng)關(guān)系maximumPoolSize連接池最大連接數(shù)對應(yīng)單實例對MySQL的最大占用minimumIdle連接池最小空閑數(shù)決定常駐連接數(shù)maxLifetime連接最大存活時間應(yīng)小于MySQL的wait_timeoutconnectionTimeout獲取連接的超時時間超過后應(yīng)用側(cè)直接報錯不等MySQL拒絕validationTimeout連接有效性驗證超時用于檢測被服務(wù)端斷開的連接這里有個黃金法則連接池的maxLifetime必須小于 MySQL 的wait_timeout。這樣連接在MySQL側(cè)被強制斷開之前應(yīng)用連接池會主動把老連接淘汰并新建避免拿到失效連接。比如MySQLwait_timeout設(shè)為600秒連接池maxLifetime設(shè)為480秒留出120秒的安全余量。另一個容易忽略的是連接池大小的設(shè)計。很多團隊直接套用“max50、min10”這類默認值完全不評估實際并發(fā)。連接池太大堆出來的都是空閑連接白占MySQL的連接數(shù)上限連接池太小高峰期請求都在排隊等連接。一個靠譜的起步值是連接池大小 業(yè)務(wù)并發(fā)峰值 × (單個請求占用連接的平均時間 / 請求平均響應(yīng)時間)這個公式本質(zhì)上就是Little‘s Law按需求出穩(wěn)態(tài)下需要的連接數(shù)。實際項目中單實例10到20個連接對絕大多數(shù)業(yè)務(wù)都夠用寧可讓少量請求排隊也不要把連接池飆到幾十上百。3.5 防呆設(shè)計max_user_connections 與賬號拆分有時候不是所有業(yè)務(wù)都值得給滿額連接配額。某個慢業(yè)務(wù)、某個批量任務(wù)、某個定時腳本它們?nèi)绻加昧诉^多連接可能擠掉核心業(yè)務(wù)的連接名額。這種情況可以用max_user_connections做賬號級別的連接上限控制。比如有一個報表賬號專門用來跑數(shù)據(jù)分析GRANT SELECT ON mydb.* TO report_user% IDENTIFIED BY password; ALTER USER report_user% WITH MAX_USER_CONNECTIONS 20;這樣就算報表任務(wù)寫得很爛、連接池配得很大它最多也就占用20個連接不會影響主業(yè)務(wù)的連接供給。還有一種更精細的做法核心業(yè)務(wù)用獨立的MySQL賬號不同微服務(wù)使用不同的賬號前綴這樣既隔離了連接配額又能在processlist里一眼看出連接歸屬。3.6 連接數(shù)滿之后的應(yīng)急逃生通道連接數(shù)打滿最尷尬的處境是你想連上去查狀態(tài)、殺連接結(jié)果連不上了因為你也是“連接”之一。這里有幾個務(wù)實的做法第一預(yù)留管理連接。MySQL始終為具備CONNECTION_ADMIN權(quán)限或MySQL 5.7及之前版本中的SUPER權(quán)限的賬號保留一條連接通道。所謂“保留”不是完全不受max_connections限制而是在連接數(shù)達到上限后管理員賬號仍然可以建立額外的連接。上限是max_connections 1這條額外的通道就是應(yīng)急逃生的關(guān)鍵。所以生產(chǎn)環(huán)境的DBA賬號一定要配置為超級權(quán)限賬號并且千萬別把這個賬號給應(yīng)用用。平時用普通賬號連接出了問題用管理員賬號連接。第二緊急調(diào)大連接數(shù)。如果是max_connections真的不夠管理員能連上之后立即執(zhí)行SET GLOBAL max_connections 2000;這是動態(tài)參數(shù)不用重啟立刻生效。但如上所述這只能緩解不能根除。緊急調(diào)整后必須排查連接的去向。第三清理僵尸連接。找到真正的空閑連接后可以直接killKILL 12345;這里有個細節(jié)要注意KILL只能殺Admin連接不用想KILL權(quán)限足夠就可以。但注意如果有正在執(zhí)行的查詢直接KILL會中斷這個查詢業(yè)務(wù)側(cè)可能報錯。對于Sleep狀態(tài)的連接殺掉是安全的。批量清理時可以先把要殺的連接拼出來確認無誤后執(zhí)行SELECT CONCAT(KILL , id, ;) FROM information_schema.processlist WHERE command Sleep AND time 600;把結(jié)果復(fù)制出來執(zhí)行也可以配合存儲過程循環(huán)處理但保險起見手工執(zhí)行更穩(wěn)妥省得誤殺活躍連接。4. 線上實戰(zhàn)連接數(shù)問題的排查與規(guī)避4.1 一個典型的連接數(shù)打滿案例某天下午一個內(nèi)部系統(tǒng)的線上數(shù)據(jù)庫突然告警Threads_connected曲線直線拉升半小時內(nèi)從200漲到1500直接觸頂。我連上去后第一件事就是查processlistSELECT command, state, COUNT(*) AS cnt FROM information_schema.processlist GROUP BY command, state ORDER BY cnt DESC;結(jié)果觸目驚心大部分連接是Sleep狀態(tài)占比超過80%而且host全部集中在同一個應(yīng)用服務(wù)網(wǎng)段。再查這個應(yīng)用對應(yīng)的連接池配置發(fā)現(xiàn)兩個問題第一連接池的minimumIdle設(shè)置得很大每個實例維持35個空閑連接20個實例就是700個常駐連接——這本身就已經(jīng)占了很大額度。第二wait_timeout是默認的8小時即便程序偶爾釋放連接失敗MySQL也不會主動回收。當(dāng)時做了三件事SET GLOBAL wait_timeout 300; SET GLOBAL max_connections 2000;然后寫了一條SQL把所有Sleep超過300秒的連接全部殺掉SELECT CONCAT(KILL , id, ;) FROM information_schema.processlist WHERE command Sleep AND time 300;執(zhí)行完連接數(shù)立刻降下來了。但既然是慢性的就要處理根因。后面協(xié)調(diào)應(yīng)用團隊改了兩處連接池minimumIdle降到5maxLifetime調(diào)到480秒并開啟連接有效性檢測。修改后觀察一周連接數(shù)穩(wěn)定在200到300之間水位健康。這個案例可以提煉出一條通用排查路徑先看狀態(tài)總量再看構(gòu)成command分組再定位來源host分組最后對癥處理參數(shù)調(diào)整連接清理。4.2 慢查詢和鎖等待怎么偽裝成連接數(shù)問題有一種場景極具迷惑性表面看是連接數(shù)暴漲實際是慢查詢和鎖等待把連接拖住了。具體來說一個慢查詢執(zhí)行幾十秒連接池里等待這個操作釋放的請求就會排隊每個排隊請求實際上占用了連接池的一個連接。連接池耗盡后新的請求只能等待connectionTimeout超時表現(xiàn)和MySQL連接數(shù)打滿幾乎一樣——應(yīng)用日志里都是一堆連接超時報錯。但此時MySQL側(cè)的Threads_connected可能并沒有超限問題出在應(yīng)用側(cè)的連接池被“餓死”了。排查這種問題要先看MySQL側(cè)的Threads_running。如果Threads_running很高比如持續(xù)超過幾十說明確實有查詢在執(zhí)行。這時候要去看慢查詢?nèi)罩径ㄎ痪唧w是哪條SQL在拖后腿同時查鎖等待SELECT * FROM sys.innodb_lock_waits;sys.innodb_lock_waits是MySQL 5.7之后提供的一個視圖直接能看到誰在等鎖、誰持有鎖、等待多久。大部分情況下找到持有鎖的事務(wù)并評估是否要kill比盲目處理連接數(shù)有效得多。見過不少團隊在這種場景下誤判成“連接數(shù)不夠”反復(fù)調(diào)大max_connections結(jié)果只是把問題推遲了慢查詢還在新連接來了繼續(xù)排隊整個系統(tǒng)卡到崩潰。記住一句話連接數(shù)是結(jié)果不是原因。排查時永遠要問一句這些連接為什么存在4.3 連接數(shù)監(jiān)控告警的最佳實踐最后系統(tǒng)性地聊一下連接數(shù)的監(jiān)控和告警建設(shè)。別小看這部分一套好用的告警體系能在故障發(fā)生前就把問題按住。建議至少設(shè)置三級告警告警級別觸發(fā)條件響應(yīng)動作關(guān)注連接數(shù)利用率 60%觀察趨勢確認是否有新業(yè)務(wù)上線警告連接數(shù)利用率 80%排查連接構(gòu)成清理異常連接嚴重連接數(shù)利用率 90% 或出現(xiàn)拒絕連接立即介入準(zhǔn)備擴容或kill連接除了比例告警還要監(jiān)控Aborted_connects的增量。這個值平時基本是0一旦往上走說明連接已經(jīng)開始被拒了這時候再處理就不如提前處理。采集方式上建議用獨立的監(jiān)控通道采集不占用業(yè)務(wù)連接配額。可以使用本地socket方式連接MySQL也可以在連接串里顯式指定一個專門的監(jiān)控賬號這個賬號只有PROCESS、SHOW DATABASES等輕量權(quán)限不會對業(yè)務(wù)造成影響。另外提醒一句Threads_running的監(jiān)控比Threads_connected更早暴露性能問題。連接數(shù)緩慢上升不可怕可怕的是Threads_running突然升高——那往往意味著線上有慢查詢或鎖風(fēng)暴正在發(fā)酵。4.4 常見問題速查表現(xiàn)象可能原因排查方法解決方案連接數(shù)緩慢持續(xù)上升連接池未回收連接 / 連接泄漏查看Sleep狀態(tài)連接數(shù)和來源host修復(fù)連接池調(diào)小wait_timeout連接數(shù)瞬間打滿連接風(fēng)暴 / 應(yīng)用重啟 / 流量尖峰查看processlist出現(xiàn)時間點緊急調(diào)大max_connectionskill多余連接檢查應(yīng)用側(cè)連接池配置應(yīng)用報連接超時但MySQL連接數(shù)未滿應(yīng)用連接池排隊 / 慢SQL占用連接查看應(yīng)用日志、MySQLThreads_running優(yōu)化慢SQL調(diào)整連接池參數(shù)連接頻繁建立和斷開連接池配置不當(dāng) / 超時過短對比Threads_created與Connections調(diào)整連接池最小/最大連接數(shù)調(diào)大thread_cache_size某些賬號占用過多連接賬號沒有配額限制按user統(tǒng)計連接數(shù)設(shè)置max_user_connections連接被殺后應(yīng)用報錯應(yīng)用使用失效連接查看應(yīng)用連接池日志開啟連接池的testOnBorrow或啟用validationQuery調(diào)整wait_timeout后應(yīng)用偶發(fā)異常連接池未感知服務(wù)端斷開應(yīng)用連接池配置設(shè)置連接池maxLifetime小于wait_timeout4.5 我最后想分享的一點經(jīng)驗連接數(shù)這件事說起來是MySQL的一個小參數(shù)但背后牽扯到應(yīng)用架構(gòu)、連接池配置、運維監(jiān)控、SQL質(zhì)量等多個層面。我踩過最深的坑就是“只管MySQL不管應(yīng)用”參數(shù)調(diào)了一輪又一輪問題卻反復(fù)出現(xiàn)。后來我才意識到MySQL側(cè)能做的其實很有限——設(shè)好上限、設(shè)好超時、做好監(jiān)控、留好逃生通道剩下的功夫全在應(yīng)用側(cè)。尤其想提醒剛接手數(shù)據(jù)庫運維的同學(xué)連接數(shù)查詢不是背幾條SQL而是要理解每個狀態(tài)值背后的含義以及它跟應(yīng)用行為之間的關(guān)系。等你遇到一次連接數(shù)打滿把整個過程從頭跟到尾捋一遍你對數(shù)據(jù)庫連接機制的理解會有一個質(zhì)的飛躍。