如何處理MySQL經常出現CPU占用率達到99%
情況說明:
最近在自己購買的linux服務器上搗鼓了一個小項目,按理說不存在CPU占用率會達到100%的情況,但事實就是經常出現。
然后,我第一反應是“卧槽,被人當礦機了?”,然后一頓查詢操作后,發現並沒有被人搗鼓,問題出現在mysql上,MySQL的CPU占用率達到了100%;這是我就很納悶了,這么小個程序,不應該啊。然后就開始了排查。
查詢了下sql進程,發現:
mysql> show processlist;
+-----+------+----------------------+-------------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+------+----------------------+-------------+---------+------+-------+------------------+
| 8 | root | 182.150.55.136:64138 | itresources | Sleep | 16686 | | NULL |
| 18 | root | 182.150.55.136:65138 | itresources | Sleep | 12886 | | NULL |
| 22 | root | 182.150.55.136:66138 | itresources | Sleep | 14486 | | NULL |
| 11 | root | 182.150.55.136:67138 | itresources | Sleep | 1116 | | NULL |
| 206 | root | localhost | NULL | Query | 0 | NULL | show processlist |
+-----+------+----------------------+-------------+---------+------+-------+------------------+
2 rows in set (0.00 sec)
發現MySQL上有大量的閑置連接。
解決措施1:
MySQL服務器所支持的最大連接數是有上限的,因為每個連接的建立都會消耗內存,因此我們希望客戶端在連接到MySQL Server處理完相應的操作后,應該斷開連接並釋放占用的內存。如果你的MySQL Server有大量的閑置連接,他們不僅會白白消耗內存,而且如果連接一直在累加而不斷開,最終肯定會達到MySQL Server的連接上限數,這會報'too many connections'的錯誤。對於wait_timeout的值設定,應該根據系統的運行情況來判斷。在系統運行一段時間后,可以通過show processlist命令查看當前系統的連接狀態,如果發現有大量的sleep狀態的連接進程,則說明該參數設置的過大,可以進行適當的調整小些。
Mysql> show variables like '%timeout%';
+-----------------------------+----------+
| Variable_name | Value |
+-----------------------------+----------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| innodb_flush_log_at_timeout | 1 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| wait_timeout | 28800 |
+-----------------------------+----------+
11 rows in set (0.00 sec)
經查詢發現原來mysql沒有進行過優化,還是原來的默認值:28800(即8個小時)
編輯 /etc/my.cnf 文件,在mysqld 下 新增 timeout參數,設置為120秒,如下:
【mysqld】
wait_timeout=120
interactive_timeout=120
注意:要同時設置interactive_timeout和wait_timeout才會生效。
最后重啟一下mysql 生效 即可!
mysql> show variables like '%timeout%';
+----------------------------+----------+
| Variable_name | Value |
+----------------------------+----------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 120 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| wait_timeout | 120 |
+----------------------------+----------+
10 rows in set (0.00 sec)
解決措施2:
如果上述問題還是不能解決的話,可以使用以下腳本定時殺掉CPU占用率95%以上的進程
#!/bin/sh
# qiyulin to monitor used CPU
record=0
while true;
do
cpu=$(top -b -n1 | grep 'mysql' | head -1 | awk '{print $9}')
pid=$(top -b -n1 | grep 'mysql' | head -1 | awk '{print $1}')
#cpu check
result=${cpu/.*}
if [[ $record == $pid ]];then kill -9 $pid;echo "$pid was killed";fi
if [[ $result > 95 || $result == 100 ]];then let record=${pid};else let record=0;fi
#echo
echo `date +%F" "%H:%M:%S`+" cpu:$result% record pid:$record pid:$pid"
sleep 60
done
使用如下命令啟動,可以保證該腳本的持續運行,並且能在CPU.out
文件中看到日志記錄:
nohup sh ./checkCPU.sh > CPU.out &