私はかなり忙しいサイトを実行しており、ピーク時間中に、netstatコマンドを実行すると、Webサーバー上のデータベースサーバーへの10.000を超える接続が開いていることがわかります。接続の99%はTIME_WAIT
状態です。
私はこのmysql変数について学びました:wait_timeout
http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout 今日。鉱山は依然としてデフォルトの28.800秒に設定されています。
この値を下げても安全ですか?
通常、私のクエリは1秒もかかりません。したがって、480分間接続を開いたままにしておくのはばかげているようです。
mysql_pconnect
の代わりにmysql_connect
の使用についても聞いたことがありますが、ホラーストーリーだけを読んでいるので、これからは遠ざけるつもりです。
Mysqlを再起動しないと、値を下げるのはかなり簡単です
タイムアウトを30秒に下げたいとしましょう
まず、これをmy.cnfに追加します
[mysqld]
interactive_timeout=30
wait_timeout=30
その後、あなたはこのようなことをすることができます
mysql -uroot -ppassword -e"SET GLOBAL wait_timeout=30; SET GLOBAL interactive_timeout=30"
これ以降のすべてのDB接続は30秒でタイムアウトします
Mysql_closeを明示的に使用してください。ほとんどの開発者がそうであるように、私はApacheを信頼しません。そうでない場合、ApacheがDB接続を閉じるがmysqldに通知せず、mysqldがタイムアウトするまでその接続を開いたままにするという競合状態が発生することがあります。さらに悪いことに、TIME_WAITがより頻繁に表示される場合があります。タイムアウト値は慎重に選択してください。
投稿した提案を適用したら、次の行を含む/root/show_mysql_netstat.sh
というスクリプトを作成します。
netstat | grep mysql > /root/mysql_netstat.txt
cat /root/mysql_netstat.txt | awk '{print $5}' | sed 's/:/ /g' | awk '{print $2}' | sort -u > /root/mysql_netstat_iplist.txt
for IP in `cat /root/mysql_netstat_iplist.txt`
do
ESCOUNT=`cat /root/mysql_netstat.txt | grep ESTABLISHED | awk '{print $5}' | grep -c "${IP}"`
TWCOUNT=`cat /root/mysql_netstat.txt | grep TIME_WAIT | awk '{print $5}' | grep -c "${IP}"`
IPPAD=`echo "${IP}..................................." | cut -b -35`
(( ESCOUNT += 1000000 ))
(( TWCOUNT += 1000000 ))
ES=`echo ${ESCOUNT} | cut -b 3-`
TW=`echo ${TWCOUNT} | cut -b 3-`
echo ${IPPAD} : ESTABLISHED:${ES} TIME_WAIT:${TW}
done
echo ; echo
netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n | sed 's/d)/d/'
これを実行すると、次のように表示されます。
[root@*** ~]# /root/ShowConnProfiles.sh
10.48.22.4......................... : ESTABLISHED:00002 TIME_WAIT:00008
10.48.22.8......................... : ESTABLISHED:00000 TIME_WAIT:00002
10.64.51.130....................... : ESTABLISHED:00001 TIME_WAIT:00000
10.64.51.133....................... : ESTABLISHED:00000 TIME_WAIT:00079
10.64.51.134....................... : ESTABLISHED:00002 TIME_WAIT:00001
10.64.51.17........................ : ESTABLISHED:00003 TIME_WAIT:01160
10.64.51.171....................... : ESTABLISHED:00002 TIME_WAIT:00000
10.64.51.174....................... : ESTABLISHED:00000 TIME_WAIT:00589
10.64.51.176....................... : ESTABLISHED:00001 TIME_WAIT:00570
1 established
1 Foreign
11 LISTEN
25 ESTABLISHED
1301 TIME_WAIT
それでも多くのmysql TIME_WAITs
が特定のWebサーバーに対して表示される場合は、次の2つのエスカレーション手順を実行します。
問題のあるWebサーバーにログインし、次のようにApacheを再起動します。
service httpd stop
sleep 30
service httpd start
必要に応じて、すべてのWebサーバーに対してこれを実行します
service httpd stop (on all web servers)
service mysql stop
sleep 120
service mysql start
service httpd start (on all web servers)
次のようにして、OSにmysqlまたはその他のアプリのTIME_WAITを強制終了させることができます。
SEC_TO_TIMEWAIT=1
echo ${SEC_TO_TIMEWAIT} > /proc/sys/net/ipv4/tcp_tw_recycle
echo ${SEC_TO_TIMEWAIT} > /proc/sys/net/ipv4/tcp_tw_reuse
これにより、TIME_WAITが1秒でタイムアウトになります。
TIME_WAIT
がいつ出現するかを絵で表しています。MySQLサーバーで多数のTIME_WAIT接続を取得している場合、それはMySQLサーバーが接続を閉じていることを意味します。この場合の最も可能性の高いケースは、ホストまたは複数のホストがブロックリストに登録された場合です。これを実行すると、これをクリアできます。
mysqladmin flush-hosts
IPごとに実行している接続数のリストを取得するには、次のコマンドを実行します。
netstat -nat | awk {'print $5'} | cut -d ":" -f1 | sort | uniq -c | sort -n
また、ポート3306への接続とtelnetに問題があるクライアントの1つにアクセスして、これが発生していることを確認することもできます。次のようなメッセージが表示されます。
telnet mysqlserver 3306
Trying 192.168.1.102...
Connected to mysqlserver.
Escape character is '^]'.
sHost 'clienthost.local' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'Connection closed by foreign Host.
MySQLサーバーへのTIME_WAIT接続が多数ある場合、コードがDBに対して多数のクエリを実行し、各クエリの接続を開いたり閉じたりしていることを意味します。
この場合、MySQLi拡張機能を使用して、DBサーバーへの永続的な接続を使用する必要があります。
http://php.net/manual/en/mysqli.persistconns.php
MySQLiを使用できない場合は、代わりにMySQL設定でthread_cache_sizeパラメータを使用する必要があります。