PHP多進程引發(fā)的msyql連接數問題
業(yè)務中有一塊采用了PHP的pcntl_fork多進程,希望能提高效率,但是在執(zhí)行的時候數據庫報錯
PDO::prepare(): Premature end of data (mysqlnd_wireprotocol.c:1244)
Packets out of order. Expected 1 received 108. Packet size=7102829
發(fā)現應該是短時間大量的鏈接寫入數據庫.導致數據庫無法響應
show variables like '%max_connections%';
show variables like '%back_log%';
修改my.ini 配置 back_log
back_log = 104
MySQL能有的連接數量。當主要MySQL線程在一個很短時間內得到非常多的連接請求,這就起作用,
然后主線程花些時間(盡管很短)檢查連接并且啟動一個新線程。back_log值指出在MySQL暫時停止回答新請求之前的短時間內多少個請求可以被存在堆棧中。
如果期望在一個短時間內有很多連接,你需要增加它。也就是說,如果MySQL的連接數據達到max_connections時,新來的請求將會被存在堆棧中,
以等待某一連接釋放資源,該堆棧的數量即back_log,如果等待連接的數量超過back_log,將不被授予連接資源。
另外,這值(back_log)限于您的操作系統(tǒng)對到來的TCP/IP連接的偵聽隊列的大小。
你的操作系統(tǒng)在這個隊列大小上有它自己的限制(可以檢查你的OS文檔找出這個變量的最大值),試圖設定back_log高于你的操作系統(tǒng)的限制將是無效的。
在linux中,/proc/sys/net/core/somaxconn這個參數,linux中內核的一個不錯的參數somaxconn
看下其解析:
對于一個TCP連接,Server與Client需要通過三次握手來建立網絡連接.當三次握手成功后,
我們可以看到端口的狀態(tài)由LISTEN轉變?yōu)镋STABLISHED,接著這條鏈路上就可以開始傳送數據了.
每一個處于監(jiān)聽(Listen)狀態(tài)的端口,都有自己的監(jiān)聽隊列.監(jiān)聽隊列的長度,與如下兩方面有關:
- somaxconn參數.
- 使用該端口的程序中l(wèi)isten()函數.
1. 關于somaxconn參數:
定義了系統(tǒng)中每一個端口最大的監(jiān)聽隊列的長度,這是個全局的參數,默認值為128,具體信息為:
Purpose:
Specifies the maximum listen backlog.
Values:
Default: 128 connections
Range: 0 to MAXSHORT
Type: Connect
Diagnosis:
N/A
Tuning
Increase this parameter on busy Web servers to handle peak connection rates.
看下FREEBSD的解析:
限制了接收新 TCP 連接偵聽隊列的大小。對于一個經常處理新連接的高負載 web服務環(huán)境來說,默認的 128 太小了。大多數環(huán)境這個值建議增加到 1024 或者更多。 服務進程會自己限制偵聽隊列的大小(例如 sendmail(8) 或者 Apache),常常在它們的配置文件中有設置隊列大小的選項。大的偵聽隊列對防止拒絕服務 DoS 攻擊也會有所幫助。
我們可以通過,
echo 1000 >/proc/sys/net/core/somaxconn
修改連接數
Mac 環(huán)境修改如下:
增加max open files。先查看一下:
$ sysctl -a | grep files
kern.maxfiles = 12288 kern.maxfilesperproc = 10240
修改為
$ sudo sysctl -w kern.maxfiles=65535 $ sudo sysctl -w kern.maxfilesperproc=65535
增加 max sockets
$ sysctl -a | grep somax
kern.ipc.somaxconn: 128 $ sudo sysctl -w kern.ipc.somaxconn=2048