文章來源:雲棲社區,經贊成受權轉載java
連接:https://yq.aliyun.com/articles/226984?spm=5176.8091938.0.0.nCksaV算法
錯誤解決記錄:
java druid 鏈接池頻繁初始化後致使的too many connection數據庫報錯。數據庫
修改/etc/my.cnf服務器
#加大鏈接列表數量併發
max_connections = 2000測試
# 調整失效鏈接清理時長 縮短優化
wait_timeout=7200ui
interactive_timeout=7200url
以上兩個配置項配合使用。線程
1、什麼是too many connection
一、重要參數
max_user_connections: The maximum number of simultaneous connections permitted to any given MySQL user account
容許的每一個用戶最大連接數,若是超過這個數值,則會報: ERROR 1203 (42000): User dba already has more than 'max_user_connections' active connections。
通常這樣的報錯只會出如今業務機器上,並不會在DB server層報錯,這樣的話DBA就沒法真正感知到錯誤,MySQL也很是貼心的推出了一個status供DBA查看:Connection_errors_max_connections
<section class="135brush" style="margin: 10px 0px; padding: 15px 20px 15px 45px; font-size: 14px; line-height: 22.39px; outline: 0px; border-width: 0px; border-style: initial; border-color: currentcolor; color: rgb(62, 62, 62); vertical-align: baseline; box-sizing: border-box; background-image: url(" https:="" mmbiz.qlogo.cn="" mmbiz_jpg="" tibrg3aoijtvy5gucqkfy5hqooqnktqmcc1e2igtetiaodqfbqphxthjdmycxagsoko2flsvbtyh2tekiklw2vcg="" 0?wx_fmt="jpeg");" ="" background-position:="" 1%="" 5px;="" background-repeat:="" no-repeat;"=""> Connection_errors_max_connections : The number of connections refused because the server max_connections limit was reached.
細心的同窗就會發現:那若是出現'max_user_connections' 的報錯,就沒法發現啦,這塊目前我還沒找到對應status。
2、什麼狀況下會發生too many connection
一、slow query 引發
真正的slow:該query的確很是慢
假裝的slow:該query自己並不慢,是受其它因素的影響致使
二、sleep 空鏈接引發
沒有任何query,只是sleep,這種狀況通常是代碼裏面沒有主動及時釋放連接致使。
3、實戰案例
一、sleep 空連接引發的TMC(too many connection簡稱)
緣由
因爲代碼沒有主動及時的釋放連接,那麼在DB Server中存在大量的sleep連接,一旦超過max_connections則報錯。
解決方案
(1)遇到這樣的報錯,若是沒有及時解決,則會致使後面的業務都一直連不上數據庫,影響面很大。
(2)因此咱們第一件事情必須是保護數據庫,kill掉這些sleep連接。關於kill這件事,又有不少技巧能夠談:
若是是人工kill,這簡直沒法完成這樣艱鉅的任務,由於業務會時刻產生這樣的sleep連接,有無盡頭
若是本身寫腳本,沒秒去kill,固然可行。可是咱們卻碰到過很是極端的狀況,那就是MySQL沒法響應你的kill請求。
因此,這裏還有一個更加靠譜的方案就是:設置wait_timeout, 它會自動幫你完成這項龐大且艱鉅的任務,且必定能夠kill掉
(3)完成上面幾個步驟以後,只能保證你的數據庫不會被壓到,且你有機會登錄進去作一些管理事情,但要完全解決還必須讓業務方處理這些sleep連接。
業務團隊排查沒有釋放連接的緣由。
一般,若是能夠,DBA協助業務方提供TMC期間top ip,讓業務方排查服務哪裏異常。
(4)啓用thread_pool功能可能能夠解決這個問題,可是因爲種種緣由沒有使用。
MySQL官方社區版不支持
沒法解決slow query引發的TMC
可能由於該組件致使其自己的問題
二、 slow query 引發的TMC
(1)先來講說真正的slow query
通常這種狀況,也很是清晰明瞭,找到它,優化它,固然前提是你的數據庫還活着。
咱們一般有SQL防火牆保護,大大下降了這樣的風險。預知SQL防火牆爲什麼物,且聽下回分享。
(2)假裝的slow query
好了,終於開始介紹這種最難的故障場景。
難點就是:由於它不是真正的slow,優化點難以尋找,所謂對症下藥,就是要找到對應的症狀,這也是難點所在。
廢話很少說,這裏介紹下前一段時間遇到的一次真實的案例。
too many connection error
threads_runnig 很是多
幾乎找不到有問題的query,沒有明顯慢的query
幾乎任何語句都變得很是慢
服務器IO壓力並不大
重要參數詳解
官方文檔的解釋我很少說,這裏簡單介紹下本身的理解。
innodb_thread_concurrency : 進入innodb存儲引擎的線程數量,若是數量滿了,就要排隊
innodb_thread_sleep_delay : 排隊等候進入innoDB的時候須要睡眠多長時間
innodb_adaptive_max_sleep_delay : 設置一個自適應的最大睡眠時間
innodb_concurrency_tickets: 一旦進入innoDB,就會獲取一個票據tickets,在票據期間能夠隨意進入innoDB不須要排隊,若是用完了,理論上則要排隊(實測後發現並非嚴格這套機制)
測試故障重現
表結構
關鍵參數設置
set global innodb_thread_concurrency = 1; --方便模擬
測試用例,三個語句開始執行時間不差1秒跟蹤結果
總結
1. 經過以上測試和結果分析得出:當query超過innodb_thread_concurrency時,其他query會等待,及時這樣的query很是快,也仍是會等待,這就是所謂的假裝的slow query。
2. 經過trx_started,now()分析得出:這些query直接的切換輪詢並非真正意義上的平均公平分配,裏面有一套本身的自適應算法,這裏面我沒有深究下去,有興趣的同窗能夠繼續瞭解源碼。
3. 既然真正的緣由找到,那麼解決方案也就很快出來,那就是讓併發線程少一點,經過咱們的omega平臺能夠很方便地得出這段時間哪些query和connect最多,那麼協助業務一塊兒溝通業務場景和優化方案,問題獲得解決。