遇到mysql超出最大連接數(shù),相信不少人第一反應就是查看mysql進程,看有沒有慢查詢,當然這個做法是完全正確的!
創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網綜合服務,包含不限于網站設計制作、成都做網站、北碚網絡推廣、小程序定制開發(fā)、北碚網絡營銷、北碚企業(yè)策劃、北碚品牌公關、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務,您的肯定,是我們最大的嘉獎;創(chuàng)新互聯(lián)為所有大學生創(chuàng)業(yè)者提供北碚建站搭建服務,24小時服務熱線:13518219792,官方網址:www.cdcxhl.com
但是很多時候真正的問題不在這里。
今天有遇到同樣的問題,一味查看mysql進程和慢查詢日志,無果。
后來老大提點了一下,查看一下nginx日志,發(fā)現(xiàn)有一兩個訪問執(zhí)行時候比較長,然后使用top命令查看了一下服務器負載,驚了,居然超高!
最后發(fā)現(xiàn)原來有一臺web分流主機掛了,導致另外幾臺web主機負載增高,從而導致了php-fpm的執(zhí)行效率降低。
那么這跟mysql有什么關系呢?原因很簡單,因為php執(zhí)行時間過長,mysql連接遲遲未釋放,就會導致連接數(shù)過多出現(xiàn)。
最后總結:其實很多時候,一個問題的根本原因并不是那么直接的呈現(xiàn)出來,需要自己去跟蹤。
老大有一句很實用的話:遇到問題先查日志(mysql、php、nginx等)
===============================================================
排查連接數(shù)過多的方法
當用戶收到鏈接數(shù)告警時,意味著連接數(shù)即將達到該實例的上限。如果實例的連接數(shù)超過了實例規(guī)定的連接數(shù),將無法創(chuàng)建新的連接,這個時候會影響用戶的業(yè)務;
Mysql 的連接通常是一個請求占用一個連接,如果該請求(update,insert,delete,select)長時間沒有執(zhí)行完畢,則會造成連接的堆積,迅速的消耗完數(shù)據(jù)庫的連接數(shù),這個時候技術支持人員就要登錄數(shù)據(jù)庫進行排序,看看到底是那些sql 占用了連接;
問題排查步驟:
1 、查看實例配置:
可登錄RDS控制臺“詳情與配置”查看實例額定鏈接數(shù),我們假設最高支持1500個鏈接
2、 查看當前的連接數(shù):
1)可登錄RDS控制臺“性能監(jiān)控”查看實例當前鏈接數(shù)。
2)或者登錄數(shù)據(jù)庫查詢當前連接,可以使用同步賬號或者用戶的業(yè)務賬號登錄數(shù)據(jù)庫,執(zhí)行show processlist;
[root@r41d05036.xy2.aliyun.com ~]# mysql -uroot -h127.0.0.1 -P3020 -e “show processlist”|wc -l
1262
可以看到該實例已經有1262 個連接
3、排查是什么動作占用了這些連接:
[root@r41d05036.xy2.aliyun.com ~]# myql -uroot -h127.0.0.1 -P3018 -e “show full processlist”/tmp/1.log
root@r14d11038.dg.aliyun.com # more /tmp/1.log
615083 my_db 223.4.49.212:54115 my_db Query 100 Sending data
INSERT INTO tmp_orders_modify (oid, tid, seller_id, status, gmt_create, gmt_modified)
SELECT oid, tid, seller_id, status, gmt_create, gmt_modified
FROM sys_info.orders WHERE
gmt_modified NAME_CONST(‘v_last’,_binary’2012-12-24 10:33:00’ COLLATE ‘binary’) AN
D gmt_modified = NAME_CONST(‘v_curr’,_binary’2012-12-24 10:32:00’ COLLATE ‘binary’)
621564 my_db 223.4.49.212:46596 my_db Query 3890 sorting result
insert into tmp_trades(sid, d, h, tc, tm, tp, ic, new_tp, old_tp)
select a.seller_id as sid,
…………..
from orders_1 as a where seller_id =1 and is_detail = ‘1’
and created date_format(‘2012-12-24 10:35:00’, ‘%Y-%m-%d %H:00:00’)
and gmt_create date_format(‘2012-12-24 10:40:00’, ‘%Y-%m-%d %H:%i:00’)
and gmt_create = date_format(‘2012-12-24 10:35:00’, ‘%Y-%m-%d%H:%i:00’)
group by d, h
order by d
……………….此處省略其他sql
4、分析連接占用的原因:
可以看到數(shù)據(jù)庫中有長時間沒有執(zhí)行完成的sql,一直占用著連接沒有釋放,而應用的請求一直持續(xù)不斷的涌入數(shù)據(jù)庫,這個時候數(shù)據(jù)庫的連接很快就被使用完;所以這個時候需要排查為什么這些sql 為什么長時間沒有執(zhí)行完畢,是索引沒有創(chuàng)建好,還是sql執(zhí)行耗時嚴重。
第一條sql:
INSERT INTO tmp_orders_modify (oid, tid, seller_id, status, gmt_create, gmt_modified)
SELECT oid, tid, seller_id, status, gmt_create, gmt_modified
FROM sys_info.orders WHERE
gmt_modified NAME_CONST(‘v_last’,_binary’2012-12-24 10:33:00’ COLLATE ‘binary’) AN
D gmt_modified = NAME_CONST(‘v_curr’,_binary’2012-12-24 10:32:00’ COLLATE ‘binary’)
是用戶從sys_info 數(shù)據(jù)庫中拉取訂單到自己的業(yè)務庫中那個,但是在orders 表上沒有gmt_modified 的索引,導致了全表掃描;(更加詳盡的排查方法可以參考:為什么我的RDS慢了);
第二條sql:
看到這條sql 正在進行sorting 排序,為什么導致sql 長時間sorting,通常情況下為排序的結果集太大導致排序不能在內存中完成,需要到磁盤上排序,進而導致了性能的下降;解決的辦法就是降低排序的結果集,常用的手段是利用索引的有序性,消除排序,或者建立適當?shù)乃饕郎p小結果集;我們可以看到第二條sql 的排序字段非常的復雜,但是我們可以看到查詢的時間范圍是很短,只有5 分鐘的時間間隔,這個時候就可以在gmt_create上創(chuàng)建一個索引,過濾掉大部分的記錄:
Alter tale order_1 add index ind_order_gmt_create(gmt_create);
(該用戶對orders 進行了分表,大概有50 多張分表需要添加gmt_create 字段的索引);
5、經過上面兩步的優(yōu)化后,用戶實例恢復正常:io 情況和connection 情況,可再次登錄RDS控制臺查看連接數(shù)。
mysql的最大連接數(shù)默認是100,
這個數(shù)值對于并發(fā)連接很多的數(shù)據(jù)庫應用是遠遠不夠的,當連接請求大于默認連接數(shù)后,就會出現(xiàn)無法連接數(shù)據(jù)庫的錯誤,因此我們需要把它適當調大一些。
調節(jié)方法為:
1.linux服務器中
:改my.cnf中的值就行了
2.Windows服務器中(我用的):
在文件“my.ini”中找到段
[mysqld],在其中添加一行
max_connections=200###
200可以更改為想設置成的值.
然后重啟"mysql"服務。
/mysqladmin所在路徑/mysqladmin
-uroot
-p
variables
輸入root數(shù)據(jù)庫賬號的密碼后可看到
|
max_connections
|
1000
|
其他需注意的:
在編程時,由于用mysql語句調用數(shù)據(jù)庫時,在每次之執(zhí)行語句前,會做一個臨時的變量用來打開數(shù)據(jù)庫,所以你在使用mysql語句的時候,記得在每次調用完mysql之后就關閉mysql臨時變量。
另外對于訪問量大的,可以考慮直接寫到文本中,根據(jù)預測的訪問量,先定義假若是100個文件文件名依次為1.
txt,2.
txt
100.
txt。
1、MySQL數(shù)據(jù)庫系統(tǒng)允許的最大可連接數(shù)max_connections。這個參數(shù)是可以設置的。如果不設置,默認是100。最大是16384。
2、數(shù)據(jù)庫當前的連接線程數(shù)threads_connected。這是動態(tài)變化的。
查看max_connections、max_connections的辦法見后。
如果
threads_connected
==
max_connections
時,數(shù)據(jù)庫系統(tǒng)就不能提供更多的連接數(shù)了,這時,如果程序還想新建連接線程,數(shù)據(jù)庫系統(tǒng)就會拒絕,如果程序沒做太多的錯誤處理,就會出現(xiàn)類似強壇的報錯信息。
因為創(chuàng)建和銷毀數(shù)據(jù)庫的連接,都會消耗系統(tǒng)的資源。而且為了避免在同一時間同時打開過多的連接線程,現(xiàn)在編程一般都使用所謂數(shù)據(jù)庫連接池技術。
但數(shù)據(jù)庫連接池技術,并不能避免程序錯誤導致連接資源消耗殆盡。
這種情況通常發(fā)生在程序未能及時釋放數(shù)據(jù)庫連接資源或其他原因造成數(shù)據(jù)庫連接資源不能釋放,但強壇系統(tǒng)估計不會發(fā)生這種低級的編程錯誤。
該錯誤的簡便的檢查辦法是,在刷新強壇頁面時,不斷監(jiān)視threads_connected的變化。如果max_connections足夠大,而
threads_connected值不斷增加以至達到max_connections,那么,就應該檢查程序了。當然,如果采用數(shù)據(jù)庫連接池技術,
threads_connected增長到數(shù)據(jù)庫連接池的最大連接線程數(shù)時,就不再增長了。
從強壇出錯的情況看,更大的可能性是數(shù)據(jù)庫系統(tǒng)沒能進行適當?shù)嘏渲?。下面提出一點建議。供參考
讓你們的工程師把MySQL的最大允許連接數(shù)從默認的100調成32000。這就不會老出現(xiàn)連接過多的問題了。
查看max_connections
進入MySQL,用命令:
show
variables
查看數(shù)據(jù)庫最大可連接數(shù)的變量值:
max_connections
查看threads_connected
進入MySQL,用命令:
show
status
查看當前活動的連接線程變量值:
threads_connected
設置max_connections
設置辦法是在my.cnf文件中,添加下面的最后紅色的一行:
[mysqld]
port=3306
#socket=MySQL
skip-l
方法1、mysql中提高max_connections的值。不要太高,依據(jù)你的內存而定。一般8G-16G內存服務器500-1000
mysql set GLOBAL max_connections=1000;
方法2、從應用層限制連接數(shù)據(jù)庫的最大連接數(shù)