最近在本身購買的linux服務器上搗鼓了一個小項目,按理說不存在CPU佔用率會達到100%的狀況,但事實就是常常出現。mysql
而後,我第一反應是「臥槽,被人當礦機了?」,而後一頓查詢操做後,發現並無被人搗鼓,問題出如今mysql上,MySQL的CPU佔用率達到了100%;這是我就很納悶了,這麼小個程序,不該該啊。而後就開始了排查。linux
查詢了下sql進程,發現: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上有大量的閒置鏈接。服務器
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秒,以下:code
【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)
若是上述問題仍是不能解決的話,可使用如下腳本定時殺掉CPU佔用率95%以上的進程ssl
#!/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 &