MySQL ลดค่า wait_timeout เป็นจำนวนการเชื่อมต่อที่เปิดน้อยลง


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การเชื่อมต่อสั้นลงเมื่อซอฟต์แวร์คาดว่าจะยังเปิดอยู่
John Gardeniers

คำตอบ:


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 บ่อยขึ้น เลือกค่าการหมดเวลาของคุณอย่างชาญฉลาด

UPDATE 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
เกือบ 2k มุมมองสำหรับสิ่งนี้และเพียง 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 ของคุณนั่นหมายความว่าคุณกำลังเรียกใช้คิวรีจำนวนมากกับ DB ของคุณและเปิด / ปิดการเชื่อมต่อสำหรับแต่ละแบบสอบถาม

ในกรณีนี้คุณควรใช้การเชื่อมต่อแบบถาวรกับเซิร์ฟเวอร์ฐานข้อมูลของคุณโดยใช้ส่วนขยาย MySQLi

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

หากคุณไม่สามารถใช้ MySQLi คุณควรใช้พารามิเตอร์ thread_cache_size แทนในการกำหนดค่า MySQL ของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.