MySQL menurunkan nilai wait_timeout ke lebih sedikit jumlah koneksi terbuka

39

Saya menjalankan situs yang agak sibuk, dan selama jam mengintip saya melihat lebih dari 10.000 koneksi terbuka ke server database saya di server web saya ketika menjalankan perintah netstat. 99% koneksi berada di TIME_WAITnegara bagian.

Saya belajar tentang variabel mysql ini: wait_timeout http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout hari ini. Milik saya masih ditetapkan pada standar 28.800 detik.

Apakah menurunkan nilai ini aman?

Bukan pertanyaan saya biasanya memakan waktu lebih dari satu detik. Jadi rasanya konyol untuk menjaga koneksi tetap terbuka selama 480 menit.

Saya juga mendengar tentang menggunakan mysql_pconnectalih-alih mysql_connect, tetapi saya tidak membaca apa pun selain cerita-cerita horor tentang itu, jadi saya pikir saya akan menjauh dari itu.

Mr.Boon
sumber
3
Ada perbedaan antara kueri dan koneksi. Anda harus setidaknya memastikan perangkat lunak situs web Anda tidak akan rusak jika wait_timeoutkoneksi yang lebih pendek ditutup ketika perangkat lunak mengharapkannya tetap terbuka.
John Gardeniers

Jawaban:

74

Menurunkan nilainya cukup sepele tanpa me-restart mysql

Katakanlah Anda ingin menurunkan batas waktu hingga 30 detik

Pertama, tambahkan ini ke my.cnf

[mysqld]
interactive_timeout=30
wait_timeout=30

Kemudian, Anda dapat melakukan sesuatu seperti ini

mysql -uroot -ppassword -e"SET GLOBAL wait_timeout=30; SET GLOBAL interactive_timeout=30"

Semua Koneksi DB setelah ini akan habis dalam 30 detik

PERINGATAN

Pastikan untuk menggunakan mysql_close secara eksplisit. Saya tidak mempercayai Apache seperti halnya kebanyakan pengembang. Jika tidak, kadang-kadang, ada kondisi lomba di mana Apache menutup Koneksi DB tetapi tidak memberi tahu mysqld dan mysqld menahan koneksi itu terbuka sampai waktu habis. Lebih buruk lagi, Anda mungkin melihat TIME_WAIT lebih sering. Pilih nilai batas waktu Anda dengan bijak.

UPDATE 2012-11-12 10:10 EDT

CAVEAT

Setelah menerapkan saran saya yang diposting, buat skrip yang disebut /root/show_mysql_netstat.shdengan baris berikut:

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/'

Ketika Anda menjalankan ini, Anda akan melihat sesuatu seperti ini:

[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

Jika Anda masih melihat banyak mysql TIME_WAITsuntuk server web mana pun, berikut adalah dua langkah peningkatan yang harus dilakukan:

ESCALATION # 1

Masuk ke server web yang melanggar dan restart apache sebagai berikut:

service httpd stop
sleep 30
service httpd start

Jika perlu, lakukan ini ke semua server web

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

ESCALATION # 2

Anda dapat memaksa OS untuk membunuh TIME_WAIT untuk mysql atau aplikasi lain dengan yang berikut:

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

Ini akan membuat TIME_WAIT kehabisan waktu dalam 1 detik.

Untuk memberikan kredit saat kredit jatuh tempo ...

RolandoMySQLDBA
sumber
1
Hampir 2k dilihat untuk ini dan hanya 2 suara (termasuk saya, jadi 1), wtf ?! Ini jawaban yang bagus. Maaf saya hanya bisa memberikan 1 suara!
jwbensley
Saya mencoba teknik ini, dan saya punya banyak koneksi CLOSE_WAIT (2622) tetapi tidak koneksi TIME_WAIT. Bagaimana saya menafsirkan hasil ini?
robguinness
4

Jika Anda mendapatkan banyak koneksi TIME_WAIT di Server MySQL maka itu berarti server MySQL sedang menutup koneksi. Kasus yang paling mungkin dalam hal ini adalah host atau beberapa host masuk daftar blokir. Anda dapat menghapus ini dengan menjalankan:

mysqladmin flush-hosts

Untuk mendapatkan daftar jumlah koneksi yang Anda miliki per IP run:

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

Anda juga dapat mengonfirmasi hal ini terjadi dengan mengunjungi salah satu klien Anda yang mengalami masalah saat menyambungkan dan telnet ke port 3306. Ini akan menampilkan pesan dengan sesuatu seperti:

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.
pengguna2566717
sumber
1

Jika Anda memiliki banyak koneksi TIME_WAIT ke server MySQL Anda, itu berarti Anda menjalankan banyak kueri terhadap DB, dan membuka / menutup koneksi untuk setiap permintaan.

Dalam hal ini, Anda harus menggunakan konektivitas terus-menerus ke server DB Anda, menggunakan ekstensi MySQLi.

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

Jika Anda tidak dapat menggunakan MySQLi, Anda sebaiknya menggunakan parameter thread_cache_size di konfigurasi MySQL Anda.

Garreth McDaid
sumber