MySQL的max_connections參數用來設置最大鏈接(用戶)數。超過這個值,系統就會拒絕接下來的鏈接請求,報錯提示:「too many connections」。對於被拒絕鏈接的請求來講,從業務角度就是數據庫不可用。mysql
每一個鏈接MySQL的用戶均算做一個鏈接,MySQL8.0.13的max_connections的默認值爲151.sql
MySQL不管如何都會保留一個用於管理員(SUPER)登錄的鏈接,用於管理員鏈接數據庫進行維護操做,即便當前鏈接數已經達到了max_connections。所以MySQL的實際最大可鏈接數爲max_connections+1;數據庫
MySQL創建鏈接的過程,成本是很高的,除了正常的網絡鏈接三次握手外,還須要作登陸權限判斷和得到這個鏈接的數據讀寫權限。安全
該參數在服務器資源夠用的狀況下應該儘可能設置大,以知足多個客戶端同時鏈接的需求。不然將會出現相似」Too many connections」的錯誤。服務器
碰到這種狀況,一個比較天然的想法,就是調高max_conncetions的值。網絡
set GLOBAL max_connections=1000;
線程
可是這樣作是有風險的。由於設計max_connections這個參數的目的是想保護MySQL,若是咱們把它改的太大,讓更多的鏈接均可以進來,那麼系統的負載可能會進一步加大,大量的資源消耗在權限驗證等邏輯上,結果可能拔苗助長,已經鏈接的線程拿不到CPU資源去執行業務的SQL請求。設計
處理這種狀況,有另外兩個有損的方法。code
第一種方法:先處理掉那些佔着鏈接可是不工做的線程。orm
對於那些不須要保持的鏈接,咱們能夠經過show processlist命令,查看狀態爲sleep的線程,經過kill connection 主動踢掉。
這個行爲跟事先設置wait_timeout的效果是同樣的。設置wait_timeout參數表示的是,一個線程空閒wait_timeout這麼多秒以後,就會被MySQL直接斷開鏈接。順便提一下,wait_timeout默認值是28800秒,即8個小時。
另外須要注意,show processlist出現的結果有多個狀態爲sleep的線程,應該優先斷開事務外空閒的鏈接.
如何判斷哪些是事務外空閒的呢?
要看具體的事務狀態,能夠查看information_schema庫的innodb_trx表。
select * from information_schema.innodb_trx \G
查詢結果裏,trx_mysql_thread_id=32,表示id=32的線程還處在事務中。
所以,若是是鏈接數過多,你能夠優先斷開事務外空閒過久的鏈接;若是這樣還不夠,再考慮斷開事務內空閒過久的鏈接。
從服務端斷開鏈接使用的命令是kill connection + id
的命令,一個客戶端處於sleep狀態時,它的鏈接被服務端主動斷開後,這個客戶端並不會立刻知道。直到客戶端再發起下一個請求的時候,纔會收到這樣的報錯「ERROR 2013(HY000):Lost connection to MySQL server during query"。
從數據庫端主動斷開鏈接多是有損的,尤爲是有的應用端收到這個錯誤後,不從新鏈接,而是直接用這個已經不能用的句柄重試鏈接。這會致使從應用端看上去,」MySQL一直沒恢復「。
第二種方法:讓數據庫跳過權限驗證階段。
若是如今數據庫確認是被鏈接行爲打掛了,那麼一種可能的作法是:讓數據庫跳過權限驗證階段,減小鏈接過程的消耗。
跳過權限驗證的方法:
重啓數據庫,並使用--skip-grant-tables參數啓動。
這樣,整個MySQL會跳過全部的權限驗證階段,包括鏈接過程和語句執行過程在內。
在MySQL8.0版本里,若是你啓用--skip-grant-tables參數,MySQL默認會把--skip-networking參數打開,表示這時候數據庫只能被本地的客戶端鏈接。可見MySQL官方對skip-grant-tables這個參數的安全問題也很重視。