您在購買RDS實例時所選擇的内存大小決定了該實例的最大連接數。在RDS管理控制台對應實例的基本信息中可看到該實例所支持的最大連接數。當RDS實例的連接數量超過該實例的最大連接數時,將無法創建新的連接,此時將會影響您業務的正常進行。
MySQL的連接通常是一個請求佔用一個連接,一般的後耑語言(例如php沒用swoole實現連接池的), 在請求(update,insert,delete,select等)長時間沒有執行完畢,則會造成連接的堆積,迅速的消耗完RDS實例的連接數。
連接數過多的優化方法
排查連接數過多的方法是什麽呢? 有以下方法可排查:
監控告警
當用戶收到連接數告警時,意味著連接數即將達到實例的上限。這是一個重要的指示,提示我們需要採取措施來處理連接數過多的情況,以避免對用戶業務的影響。
分析連接佔用
MySQL的連接通常是一個請求佔用一個連接。如果某個請求(如update、insert、delete、select)長時間未執行完畢,就會導致連接堆積,迅速消耗數據庫的連接數。在這種情況下,技術支持人員需要登錄數據庫並檢查連接的佔用情況,找出具體哪些SQL語句佔用了連接。
優化SQL語句
一旦確定哪些SQL語句佔用了連接,就需要對其進行優化。通過優化查詢語句、添加索引、調整數據庫配置等方式,提升SQL語句的執行效率,從而減少連接佔用的時間。
增加連接數限制
如果經過優化後仍然存在連接數過多的問題,可以考慮增加數據庫實例的連接數限制。這需要根據實際情況評估數據庫的硬件資源和負載情況,確保增加連接數不會對系統性能造成過大的影響。
連接池
使用連接池可以更好地管理數據庫連接,避免連接的頻繁創建和銷毀,從而提高連接的複用率和效率。連接池可以幫助平衡連接的分配和釋放,有效控制連接數,減少連接數過多的情況發生。
場景: 阿裡雲RDS控制台下的優化
查看實例配置:
如果是阿裡雲的RDS, 你可登錄RDS控制台“詳情與配置”查看實例額定鏈接數,我們假設最高支持1500個鏈接
查看當前的連接數:
1)可登錄RDS控制台“性能監控”查看實例當前鏈接數。
2)或者登錄數據庫查詢當前連接,可以使用同步帳號或者用戶的業務帳號登錄數據庫,執行show processlist;
[root@r41d05036.xy2.aliyun.com ~]# mysql -uroot -h127.0.0.1 -P3020 -e "show processlist"|wc -l 1262
可以看到該實例已經有1262 個連接
排查是啥動作佔用了那麽多連接:
[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
分析連接佔用的原因:
可以看到數據庫中有長時間沒有執行完成的sql,一直佔用著連接沒有釋放,而應用的請求一直持續不斷的湧入數據庫,這個時候數據庫的連接很快就被使用完;所以這個時候需要排查爲什麽這些sql 爲什麽長時間沒有執行完畢,是索引沒有創建好,還是sql執行耗時嚴重。
第一條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') AND gmt_modified >= NAME_CONST('v_curr',_binary'2012-12-24 10:32:00' COLLATE 'binary')
是用戶從sys_info 數據庫中拉取訂單到自己的業務庫中那個,但是在orders 表上沒有gmt_modified 的索引,導致了全表掃描;(更加詳盡的排查方法可以參考:爲什麽我的RDS慢了);
第二條sql:
看到這條sql 正在進行sorting 排序,爲什麽導致sql 長時間sorting,通常情況下爲排序的結果集太大導致排序不能在内存中完成,需要到磁盤上排序,進而導致了性能的下降;解決的辦法就是降低排序的結果集,常用的手段是利用索引的有序性,消除排序,或者建立適當的索引減小結果集;我們可以看到第二條sql 的排序字段非常的複雜,但是我們可以看到查詢的時間範圍是很短,只有5 分鍾的時間間隔,這個時候就可以在gmt_create上創建一個索引,過濾掉大部分的記錄:
Alter tale order_1 add index ind_order_gmt_create(gmt_create);
(該用戶對orders 進行了分表,大概有50 多張分表需要添加gmt_create 字段的索引);
經過上面兩步的優化後,用戶實例恢複正常:io 情況和connection 情況,可再登錄一回RDS控制台查看連接數。