Зниження значення wait_timeout MySQL для зменшення кількості відкритих з'єднань


39

Я запускаю досить зайнятий сайт, і протягом пік годин я бачу понад 10 000 відкритих підключень до мого сервера бази даних на своєму веб-сервері, коли запускаю команду netstat. 99% зв’язків у TIME_WAITдержаві.

Я дізнався про цю змінну mysql: wait_timeout http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout сьогодні. Шахта все ще встановлена ​​за замовчуванням 28 800 секунд.

Чи безпечне зниження цього значення?

Не мої запити зазвичай займають більше секунди. Тож здається нерозумним тримати зв’язок відкритим протягом 480 хвилин.

Я також чув про використання mysql_pconnectзамість цього mysql_connect, але я не читав нічого, окрім страшилок про це, тому думаю, що буду триматися осторонь цього.


3
Існує різниця між запитами та підключеннями. Потрібно принаймні переконатися, що програмне забезпечення вашого веб-сайту не розірветься, якщо коротше wait_timeoutпризведе до закриття з'єднання, коли програмне забезпечення очікує, що воно залишатиметься відкритим.
Джон Гарденєр

Відповіді:


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"

Усі з'єднання БД після цього закінчуються через 30 секунд

УВАГА

Переконайтесь, що явно використовуйте mysql_close. Я не довіряю Apache, як це робить більшість розробників. Якщо ні, то іноді виникає умова гонки, коли Apache закриває з'єднання з БД, але не повідомляє 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

Якщо ви все ще бачите безліч mysql TIME_WAITsдля будь-якого веб-сервера, ось два кроки:

ЕКСАЛІЯ №1

Увійдіть на веб-сервер, який порушує вас, і перезапустіть apache таким чином:

service httpd stop
sleep 30
service httpd start

Якщо потрібно, зробіть це на всіх веб-серверах

service httpd stop (on all web servers)
service mysql stop
sleep 120
service mysql start
service httpd start (on all web servers)

ЕКСАЛІЯ №2

Ви можете змусити ОС знищити TIME_WAIT для mysql або будь-якого іншого додатка з наступним:

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. Як слід інтерпретувати цей результат?
robguinness

4

Якщо ви отримуєте багато TIME_WAIT-підключень на сервері MySQL, це означає, що MySQL-сервер закриває з'єднання. Найімовірнішим у цьому випадку буде те, що хост або кілька хостів потрапили до списку блоків. Це можна очистити, запустивши:

mysqladmin flush-hosts

Щоб отримати список кількості підключень, які ви маєте за виконання IP-адреси:

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

Ви також можете підтвердити, що це відбувається, перейшовши до одного із своїх клієнтів, у якого виникають проблеми з підключенням та telnet до порту 3306. Він покаже повідомлення з чимось на зразок:

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

Якщо у вас є багато TIME_WAIT підключень до вашого сервера MySQL, це означає, що код виконує безліч запитів до вашої БД, а також відкриває / закриває з'єднання для кожного запиту.

У цьому випадку вам слід використовувати стійке підключення до вашого сервера БД, використовуючи розширення MySQLi.

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

Якщо ви не можете використовувати MySQLi, слід замість цього використовувати параметр thread_cache_size у вашій конфігурації MySQL.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.