MySQLはwait_timeout値を下げて、開いている接続の数を減らします


39

私はかなり忙しいサイトを運営しており、ピーク時間中に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ましたが、私はそれについてのホラーストーリーしか読んでいませんでした。


3
クエリと接続には違いがあります。少なくともwait_timeout、ソフトウェアが開いたままであると予期しているときに接続が閉じた場合、Webサイトソフトウェアが破損しないことを確認する必要があります。
ジョンガーデニアーズ

回答:


74

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がより頻繁に表示される場合があります。タイムアウト値を賢明に選択してください。

更新2012-11-12 10:10 EDT

警告

投稿された提案を適用した後/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

TIME_WAITs特定のWebサーバーでまだ多くのmysqlが表示される場合は、次の2つのエスカレーション手順を実行してください。

エスカレーション#1

問題のある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)

エスカレーション#2

次を使用して、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秒でタイムアウトになります。

クレジットを支払うべき場所にクレジットを与えるには...


1
これに対してほぼ2万回のビューと、たった2票(私の場合も含めて1票)、wtf ?! これは素晴らしい答えです。申し訳ありませんが、1つの投票しかできません。
jwbensley

この手法を試しましたが、多くのCLOSE_WAIT接続(2622)がありましたが、TIME_WAIT接続はありませんでした。この結果をどのように解釈すればよいですか?
ロブギネス

4

MySQLサーバーで多くのTIME_WAIT接続を取得している場合は、MySQLサーバーが接続を閉じていることを意味します。この場合の最も可能性の高いケースは、1つまたは複数のホストがブロックリストに登録されたことです。これをクリアするには、次を実行します。

mysqladmin flush-hosts

IPごとの接続数のリストを取得するには、次を実行します。

 netstat -nat | awk {'print $5'} | cut -d ":" -f1 | sort | uniq -c | sort -n

また、ポート3306への接続とtelnetに問題があるクライアントのいずれかにアクセスして、これが発生していることを確認できます。次のようなメッセージが表示されます。

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.

1

MySQLサーバーへのTIME_WAIT接続が多数ある場合、コードはDBに対して多くのクエリを実行し、各クエリに対して接続を開いたり閉じたりすることを意味します。

この場合、MySQLi拡張機能を使用して、DBサーバーへの永続的な接続を使用する必要があります。

http://php.net/manual/en/mysqli.persistconns.php

MySQLiを使用できない場合は、代わりにMySQL構成でthread_cache_sizeパラメーターを使用する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.