MySQL hạ giá trị Wait_timeout xuống số lượng kết nối mở thấp hơn


39

Tôi chạy một trang web khá bận rộn và trong những giờ nhìn trộm tôi thấy hơn 10.000 kết nối mở đến máy chủ cơ sở dữ liệu của mình trên máy chủ web của mình khi chạy lệnh netstat. 99% các kết nối là trong TIME_WAITtiểu bang.

Tôi đã tìm hiểu về biến mysql này: wait_timeout http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout ngày hôm nay. Của tôi vẫn được đặt ở mặc định 28.800 giây.

Là hạ thấp giá trị này an toàn?

Không phải truy vấn của tôi thường mất hơn một giây. Vì vậy, có vẻ ngớ ngẩn khi giữ một kết nối mở trong 480 phút.

Tôi cũng đã nghe về việc sử dụng mysql_pconnectthay vì mysql_connect, nhưng tôi đã không đọc được gì ngoài những câu chuyện kinh dị về nó, vì vậy tôi nghĩ rằng tôi sẽ tránh xa điều đó.


3
Có một sự khác biệt giữa các truy vấn và kết nối. Bạn ít nhất cần đảm bảo phần mềm trang web của bạn sẽ không bị hỏng nếu ngắn hơn wait_timeoutkhiến kết nối bị đóng khi phần mềm mong muốn nó vẫn mở.
John Gardeniers

Câu trả lời:


74

Việc hạ thấp giá trị là khá nhỏ mà không cần khởi động lại mysql

Giả sử bạn muốn giảm thời gian chờ xuống 30 giây

Đầu tiên, thêm cái này vào my.cnf

[mysqld]
interactive_timeout=30
wait_timeout=30

Sau đó, bạn có thể làm một cái gì đó như thế này

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

Tất cả các kết nối DB sau này sẽ hết thời gian trong 30 giây

CẢNH BÁO

Hãy chắc chắn để sử dụng rõ ràng sử dụng mysql_c Đóng. Tôi không tin tưởng Apache như hầu hết các nhà phát triển làm. Nếu không, đôi khi, có một điều kiện cuộc đua trong đó Apache đóng Kết nối DB nhưng không thông báo cho mysqld và mysqld giữ kết nối đó mở cho đến khi hết thời gian. Thậm chí tệ hơn, bạn có thể thấy TIME_WAIT thường xuyên hơn. Chọn giá trị thời gian chờ của bạn một cách khôn ngoan.

CẬP NHẬT 2012-11-12 10:10 EDT

CẨN THẬN

Sau khi áp dụng các đề xuất đã đăng của tôi, hãy tạo một tập lệnh được gọi /root/show_mysql_netstat.shvới các dòng sau:

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

Khi bạn chạy cái này, bạn sẽ thấy một cái gì đó như thế này:

[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

Nếu bạn vẫn thấy rất nhiều mysql TIME_WAITscho bất kỳ máy chủ web cụ thể nào, đây là hai bước leo thang cần thực hiện:

THAM GIA # 1

Đăng nhập vào máy chủ web vi phạm và khởi động lại apache như sau:

service httpd stop
sleep 30
service httpd start

Nếu cần, hãy làm điều này với tất cả các máy chủ 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

Bạn có thể buộc HĐH tiêu diệt TIME_WAITs cho mysql hoặc bất kỳ ứng dụng nào khác bằng cách sau:

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

Điều này sẽ khiến TIME_WAIT hết thời gian trong 1 giây.

Cung cấp tín dụng khi tín dụng đáo hạn ...


1
Gần 2k lượt xem cho điều này và chỉ có 2 lượt bình chọn (bao gồm cả của tôi, vì vậy 1), wtf?! Đây là một câu trả lời tuyệt vời. Xin lỗi tôi chỉ có thể bỏ phiếu 1!
jwbensley

Tôi đã thử kỹ thuật này và tôi có rất nhiều kết nối CLOSE_WAIT (2622) nhưng không có kết nối TIME_WAIT. Làm thế nào tôi nên giải thích kết quả này?
cướp

4

Nếu bạn nhận được nhiều kết nối TIME_WAIT trên Máy chủ MySQL thì điều đó có nghĩa là máy chủ MySQL đang đóng kết nối. Trường hợp rất có thể trong trường hợp này sẽ là một máy chủ hoặc một số máy chủ có trong danh sách chặn. Bạn có thể xóa điều này bằng cách chạy:

mysqladmin flush-hosts

Để có danh sách số lượng kết nối bạn có trên mỗi lần chạy IP:

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

Bạn cũng có thể xác nhận điều này đang xảy ra bằng cách đến một trong những khách hàng của bạn đang gặp sự cố khi kết nối và telnet đến cổng 3306. Nó sẽ hiển thị một thông báo với nội dung như:

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

Nếu bạn có nhiều kết nối TIME_WAIT với máy chủ MySQL của mình, điều đó có nghĩa là mã của bạn đang chạy rất nhiều truy vấn đối với DB của bạn và mở / đóng kết nối cho mỗi truy vấn.

Trong trường hợp này, bạn nên sử dụng kết nối liên tục đến máy chủ DB của mình, sử dụng tiện ích mở rộng MySQLi.

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

Nếu bạn không thể sử dụng MySQLi, thay vào đó bạn nên sử dụng tham số thread_cache_size trong cấu hình MySQL của mình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.