MySQL中經典的too many connection怎麼破

 

文章來源:雲棲社區,經贊成受權轉載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&quot;);" ="" 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,優化點難以尋找,所謂對症下藥,就是要找到對應的症狀,這也是難點所在。


廢話很少說,這裏介紹下前一段時間遇到的一次真實的案例。

故障症狀

 

  1. too many connection error

  2. threads_runnig 很是多

  3. 幾乎找不到有問題的query,沒有明顯慢的query

  4. 幾乎任何語句都變得很是慢

  5. 服務器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最多,那麼協助業務一塊兒溝通業務場景和優化方案,問題獲得解決。

相關文章
相關標籤/搜索