mysql 伺服器的連線的會耗用資源,例如連線數、頻寬、記憶體、cpu等。如果遇到類似惡意的阻斷式DOS/DDOS的攻擊,一下吃下太多的連線,瞬間就會使伺服器異常。
這時除了重啟以外,還有沒有別的招?
查看目前的連線
使用 show processlist 來查看目前的連線,可以查看出效能的瓶頸。
mysql> SHOW PROCESSLIST;
+-------+------+-----------------+------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-------+------+-----------------+------+---------+------+-------+------------------+
| 14850 | axer | localhost | NULL | Query | 0 | NULL | SHOW PROCESSLIST |
| 14852 | note | localhost:62258 | note | Sleep | 0 | | NULL |
+-------+------+-----------------+------+---------+------+-------+------------------+
2 rows in set (0.00 sec)
+-------+------+-----------------+------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-------+------+-----------------+------+---------+------+-------+------------------+
| 14850 | axer | localhost | NULL | Query | 0 | NULL | SHOW PROCESSLIST |
| 14852 | note | localhost:62258 | note | Sleep | 0 | | NULL |
+-------+------+-----------------+------+---------+------+-------+------------------+
2 rows in set (0.00 sec)
若連線的方式使用 persistent 方式,操作結束時不會立刻斷連,而會進入 Sleep 狀態
其中 Sleep 就是作完動作尚未 timeout 的連線,這時另一個欄位 Time 代表他 "sleep" 的時間,以上例而言為0 代表剛睡而已。如果要殺掉那個程序,就下指令
mysql> kill 14852;
查看及修改等待結束的時間
我們可以查看預設的連線時間,變數 wait_timeout:
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 |
| rpl_stop_slave_timeout | 31536000 |
| slave_net_timeout | 3600 |
| wait_timeout | 28800 |
+-----------------------------+----------+
12 rows in set (0.00 sec)
+-----------------------------+----------+
| 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 |
| rpl_stop_slave_timeout | 31536000 |
| slave_net_timeout | 3600 |
| wait_timeout | 28800 |
+-----------------------------+----------+
12 rows in set (0.00 sec)
預設是 28800 秒,真是驚人,那表示如果你的存取方式是permanent的連線狀態,一旦建立完沒有手動結束的話,他會一直睡到28800秒才會關閉,也就是約8個小時。這個值不要設太小,否則遇到比較耗時的查詢,還來不及查完就出現MySQL has gone away的錯誤。
依我的經驗180秒很足夠
執行期修改,設定為180秒
mysql> set wait_timeout=180;
永久設定
修改 /etc/my.cnf
[mysqld]
wait_timeout=180
wait_timeout=180
重啟後生效
原文 2010-03-17 00:31:07