公司開發反應數據庫加載慢,mongodb和mysql的負載較高;后進入mysql中發現,sleep進程特別多,如下:
mysql> show full processlist;
+-------+------+----------------------+-------+---------+------+-------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-------+------+----------------------+-------+---------+------+-------+-----------------------+
| 14 | root | 192.168.138.12:36854 | DMUSS | Sleep | 0 | | NULL |
| 73 | root | 192.168.138.12:36870 | DMUSS | Sleep | 3 | | NULL |
| 78 | root | 192.168.138.12:36886 | DMUSS | Sleep | 1 | | NULL |
| 72800 | root | 223.71.188.222:53298 | DMUSS | Sleep | 1450 | | NULL |
| 72978 | root | 223.71.188.222:64691 | DMUSS | Sleep | 1347 | | NULL |
| 72979 | root | 223.71.188.222:63611 | NULL | Sleep | 1346 | | NULL |
| 73009 | root | 223.71.188.222:63617 | DMUSS | Sleep | 1336 | | NULL |
| 73016 | root | 223.71.188.222:64727 | DMUSS | Sleep | 1337 | | NULL |
| 73518 | root | localhost | NULL | Query | 0 | init | show full processlist |
| 73709 | root | 223.71.188.222:63821 | DMUSS | Sleep | 1028 | | NULL |
| 73712 | root | 223.71.188.222:54680 | DMUSS | Sleep | 1027 | | NULL |
| 73714 | root | 223.71.188.222:63826 | DMUSS | Sleep | 1026 | | NULL |
| 73723 | root | 223.71.188.222:63828 | DMUSS | Sleep | 1021 | | NULL |
| 73942 | root | 223.71.188.222:55011 | DMUSS | Sleep | 681 | | NULL |
| 73943 | root | 223.71.188.222:55012 | DMUSS | Sleep | 698 | | NULL |
| 74250 | root | 223.71.188.222:65397 | DMUSS | Sleep | 771 | | NULL |
| 74266 | root | 223.71.188.222:65408 | DMUSS | Sleep | 765 | | NULL |
| 74289 | root | 223.71.188.222:65415 | DMUSS | Sleep | 757 | | NULL |
| 76719 | root | 223.71.188.222:57470 | DMUSS | Sleep | 0 | | NULL |
+-------+------+----------------------+-------+---------+------+-------+-----------------------+
19 rows in set (0.00 sec)
sleep進程嚴重消耗mysql服務器資源(主要是cpu, 內存),並可能導致mysql崩潰。
下面是mysql手冊給出的解釋:
1)客戶端程序在退出之前沒有調用mysql_close()。[寫程序的疏忽,或者數據庫的db類庫沒有自動關閉每次的連接]
2)客戶端sleep的時間在wait_timeout或interactive_timeout規定的秒內沒有發出任何請求到服務器。[類似常連,類似於不完整的tcp ip協議構造,服務端一直認為客戶端仍然存在(有可能客戶端已經斷掉了)]
3)客戶端程序在結束之前向服務器發送了請求還沒得到返回結果就結束掉了。[參看:tcp ip協議的三次握手]
造成睡眠連接過多的原因?
1)使用了太多持久連接。
2)程序中,沒有及時關閉mysql連接。
3)數據庫查詢不夠優化,過度耗時。
解決方法
wait_timeout, 即可設置睡眠連接超時秒數,如果某個連接超時,會被mysql自然終止
修改mysql配置文件
[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
skip-name-resolve
query_cache_type = 1
wait_timeout = 20
interactive_timeout=20
重啟mysql
mysql> show global 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 | 20 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| rpl_stop_slave_timeout | 31536000 |
| slave_net_timeout | 3600 |
| wait_timeout | 20 |
+-----------------------------+----------+
12 rows in set (0.00 sec)
mysql> show full processlist;
+----+------+---------------------+-------+---------+------+-------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+---------------------+-------+---------+------+-------+-----------------------+
| 66 | root | 192.168.138.12:57028 | DMUSS | Sleep | 0 | | NULL |
| 69 | root | 192.168.138.12:57044 | DMUSS | Sleep | 2 | | NULL |
| 71 | root | 192.168.138.12:57048 | DMUSS | Sleep | 3 | | NULL |
| 78 | root | localhost | NULL | Query | 0 | init | show full processlist |
+----+------+---------------------+-------+---------+------+-------+-----------------------+
mysql的配置文件中,有一項:
不停實例:
mysql> set global interactive_timeout=30;
Query OK, 0 rows affected (0.00 sec)
mysql> set global wait_timeout=30;
Query OK, 0 rows affected (0.00 sec)
mysql> show global 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 | 30 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| rpl_stop_slave_timeout | 31536000 |
| slave_net_timeout | 3600 |
| wait_timeout | 30 |
+-----------------------------+----------+
12 rows in set (0.00 sec)
生效;
mysql> show variables like '%timeout'; 看不到配置生效;
說法1:interactive_timeout和wait_timeout的默認值都是28800(8小時)當這兩個參數同時出現在里時,會以interactive_timeout的值為准。也就是說不管wait_timeout的值是多少,用show variables like '%timeout%';查看時顯示的兩個值都是一樣的,並且都是interactive_timeout的值。
說法2:如果查詢時使用的是show variables的話,會發現設置好像並沒有生效,這是因為單純使用show variables的話就等同於使用的是show session variables,查詢的是會話變量,只有使用show global variables,查詢的才是全局變量。網絡上很多人都抱怨說他們set global之后使用show variables查詢沒有發現改變,原因就在於混淆了會話變量和全局變量,如果僅僅想修改會話變量的話,可以使用類似set wait_timeout=10;或者set session wait_timeout=10;這樣的語法。
當然,更根本的方法,還是從以上三點排查之:
1. 程序中,不使用持久鏈接,即使用mysql_connect而不是mysql_pconnect。
2. 程序執行完畢,應該顯式調用mysql_close
3. 只能逐步分析系統的SQL查詢,找到查詢過慢的SQL,優化之.
參考文章:https://yq.aliyun.com/ziliao/22247 https://www.cnblogs.com/azhqiang/p/5454000.html