最近所開發的系統中出現大量數據庫sleep狀態的空連接,于此同時通過Log發現系統中通過php的curl請求第三方API接口的反饋出現大量異常,不由得把2者聯系起來分析原因。日志反應第三方接口響應緩慢,并且結果為空,原因不明,但是能想象到php發出curl請求后一直等待連接返回,等待過程中數據庫連接開始sleep,直到curl超時,進程執行完畢數據庫鏈接得以釋放。
轉載2個與php進程阻塞有關的文章
php+mysql+memcache實戰型技術測試(答案公布)
出兩個變態的題目,題目很變態,但是都是實戰中遇到的真實案例,
1:我寫一個程序,既要使用mysql也要使用memcache,
第一行是 mysql\_connect,第二行是memcache\_connect
換過來寫,第一行是memcache\_connect,第二行是mysql\_connect
caoz發現實踐中這兩種寫法有很大的區別,區別在哪里?
2:我寫一個程序,使用了mysql,生成了一個頁面最后用 echo $html; 輸出
一種寫法是
mysql\_close();
echo $html;
另一種是
echo $html;
mysql\_close();
caoz發現實踐中這兩種區別很大,區別在哪里?
兩個全是實踐中發現并調整的案例。
\---------------------------------------------半夜黑眼圈更新博客的分割線--------------------------------
caoz寫程序不是追求BT的人,caoz經常和工程師強調,不追求極端的技術體現或者技術炫耀,所以,如果讀者認為這里的題目是為了所謂的諸如某個寫法比某個寫法資源開銷小一點或者其他什么,那么這真不是caoz的本意。
這兩道題都是真實運營環境中遇到的典型案例,典型在哪里呢?就是當你遇到一個系統故障的時候,你怎么分析,怎么思考,怎么判斷多種關聯因素的影響,所以這個題目答出答不出并不重要,重要的是怎么思考系統彼此的關系。
一個典型的系統故障是, mysql 連接過多,或者說too many
connections,這個問題困擾了我們很久,如果這是因為索引導致的,或者因為數據并發請求導致的,定位到原因并不復雜,但是當上述問題解決后,詭異的現象發生了,數據庫幾乎沒有壓力,沒有阻塞進程,沒有慢查詢,但是mysql連接很多,而且都是sleep連接。此時,webserver的鏈接也很多,換句話說,因為php執行阻塞,導致mysql鏈接無法迅速釋放,那么,php為什么會阻塞?
逐個斷點分析發現,原來echo耽誤了最多時間。
這個事情讓caoz漲了點經驗,之前從來不會認為echo是一個時間阻塞點(如果你在本機測試,你會認為其時間延遲幾乎是0),但是實例跟蹤發現,echo實際上在我們的工作環境中,代表的網絡傳輸的過程,換言之,會因為路由,帶寬的因素而等待,而此時,mysql的鏈接還在那里沒有釋放,是的,看到題目每個人都會想到,mysql\_close要放在echo后面,但是為什么echo會耽誤時間,很少人會想到。當然,這個也與工作環境有關,caoz只知道我們配置的webserver會有這種情況,是不是存在其他的配置模式,caoz沒有實測,不敢亂說,但是這里的經驗是,mysql\_close放到echo前面,大量的sleep鏈接會迅速減少。
echo并不耗費太多系統資源,但是會等待網絡傳輸,在高并發的網絡環境下,注意這一點對數據庫很有好處。
這個問題解決后,mysql健康了很多,但是偶然還會出現鏈接過多的問題,又困擾了很久,直到有一天,根據用戶反饋的一些錯誤信息,發現memcached服務器有不穩定因素,原來是memcached流量過高產生阻塞,php進程等待鏈接,導致mysql鏈接大量等待,這是第一個題目的由來,其實這個題目本身沒有標準答案,但是應該有一個意識,當你在一個腳本中同時啟動A,B兩個鏈接,那么如果你不能保證這兩個鏈接是必然可靠的(通常是無法保障的),那么后者一旦阻塞,就會導致前者大量鏈接等待,而前者阻塞,通常不會影響后者。所以,這個答案取決于,哪個鏈接對你的應用更重要,以及哪個鏈接有更大的并發支撐性。
兩道題說到底就是一個意思,當遇到系統問題和故障的時候,多想想一些關聯的因素影響,多思考整個架構響應先后過程的邏輯,數據庫連接過多,不一定是數據庫造成的,web鏈接過多,也不一定非要去優化webserver,關聯因素可能才是根源,解決了根源,表象才會徹底解決。
\------------------------------------------------------------------------------------------------------------------------------
文章二:【減少MySQL的Sleep進程有效方法】
經常遇到很多朋友問到,他的MySQL中有很多Sleep進程,嚴重占用MySQL的資源,現在分析一下出現這種現象的原因和解決辦法:
1,通常來說,MySQL出現大量Sleep進程是因為采用的PHP的MySQL長鏈接數據庫方式,即使用了mysql\_pconnect來打開鏈接數據庫,解決辦法就是使用“短”鏈接,即mysql\_connect函數。
2,在使用mysql\_connect短鏈接方式打開數據庫,每個頁面在打開數據庫后,執行SQL完成,當頁面腳本結束的時候,這個MySQL連接會自動關閉并且釋放內存。但仍然出現大量Sleep進程,可以看看網站是否存在以下幾個方面的問題。
A,硬盤上存在大量的靜態文件,或者WEB服務器負荷太重,在處理HTTP請求響應變得太慢,這樣也有可能導致出現大量Sleep進程,解決方法適當調整WEB服務參數和文件,一味的靜態或者緩存化網頁內容并不是靈丹妙藥。
B,在網頁腳本中,有些計算和應用可能非常耗時,比如在0秒的時候打開數據庫執行完一段SQL代碼后,網頁腳本隨即花了20秒鐘進行一段復雜的運算,或者是require了一個龐大的PHP文件(比如含有幾千個違規關鍵字的過濾函數),哪么這個時候在MySQL后臺看到的進程中,這個20秒的過程
MySQL并沒有做任何事情了,一直處于Sleep狀態,直到這個頁面執行完畢或者達到wait\_timeout值(被強行關閉),優化網頁腳本,盡量讓程序快速運行,或者在執行這段耗時的運行過程中,執行mysql\_close把當前MySQL鏈接強行關閉。
C,在采集站中,MySQL中大量的Sleep進程這類現象尤其明顯(比如很多網友問道DeDeCMS的MySQL中出現大量Sleep),因為大部的采集器頁面在運行過程中,事先打開了一個MySQL鏈接(可能是為了驗證用戶權限等),然后開始使用file\_get\_contents之類的操作去獲取一個遠程的網頁內容,如果這個遠程的站點訪問速度太慢,比如花了10秒時間才把網頁取回,哪么當前采集腳本程序就一直阻塞在這里,并且MySQL啥事也沒干,一直處于Sleep狀態。解決方法同上,在發出file\_get\_contents采集遠程網頁的時候,使用mysql\_close強行關閉
MySQL的連接,等采集完成在適當需要的時候再重新mysql\_connect即可。
- 技能知識點
- 對死鎖問題的理解
- 文件系統原理:如何用1分鐘遍歷一個100TB的文件?
- 數據庫原理:為什么PrepareStatement性能更好更安全?
- Java Web程序的運行時環境到底是怎樣的?
- 你真的知道自己要解決的問題是什么嗎?
- 如何解決問題
- 經驗分享
- GIT的HTTP方式免密pull、push
- 使用xhprof對php7程序進行性能分析
- 微信掃碼登錄和使用公眾號方式進行掃碼登錄
- 關于curl跳轉抓取
- Linux 下配置 Git 操作免登錄 ssh 公鑰
- Linux Memcached 安裝
- php7安裝3.4版本的phalcon擴展
- centos7下php7.0.x安裝phalcon框架
- 將字符串按照指定長度分割
- 搜索html源碼中標簽包的純文本
- 更換composer鏡像源為阿里云
- mac 隱藏文件顯示/隱藏
- 谷歌(google)世界各國網址大全
- 實戰文檔
- PHP7安裝intl擴展和linux安裝icu
- linux編譯安裝時常見錯誤解決辦法
- linux刪除文件后不釋放磁盤空間解決方法
- PHP開啟異步多線程執行腳本
- file_exists(): open_basedir restriction in effect. File完美解決方案
- PHP 7.1 安裝 ssh2 擴展,用于PHP進行ssh連接
- php命令行加載的php.ini
- linux文件實時同步
- linux下php的psr.so擴展源碼安裝
- php將字符串中的\n變成真正的換行符?
- PHP7 下安裝 memcache 和 memcached 擴展
- PHP 高級面試題 - 如果沒有 mb 系列函數,如何切割多字節字符串
- PHP設置腳本最大執行時間的三種方法
- 升級Php 7.4帶來的兩個大坑
- 不同域名的iframe下,fckeditor在chrome下的SecurityError,解決辦法~~
- Linux find+rm -rf 執行組合刪除
- 從零搭建Prometheus監控報警系統
- Bug之group_concat默認長度限制
- PHP生成的XML顯示無效的Char值27消息(PHP generated XML shows invalid Char value 27 message)
- XML 解析中,如何排除控制字符
- PHP各種時間獲取
- nginx配置移動自適應跳轉
- 已安裝nginx動態添加模塊
- auto_prepend_file與auto_append_file使用方法
- 利用nginx實現web頁面插入統計代碼
- Nginx中的rewrite指令(break,last,redirect,permanent)
- nginx 中 index try_files location 這三個配置項的作用
- linux安裝git服務器
- PHP 中運用 elasticsearch
- PHP解析Mysql Binlog
- 好用的PHP學習網(持續更新中)
- 一篇寫給準備升級PHP7的小伙伴的文章
- linux 安裝php7 -系統centos7
- Linux 下多php 版本共存安裝
- PHP編譯安裝時常見錯誤解決辦法,php編譯常見錯誤
- nginx upstream模塊--負載均衡
- 如何解決Tomcat服務器打開不了HOST Manager的問題
- PHP的內存泄露問題與垃圾回收
- Redis數據結構 - string字符串
- PHP開發api接口安全驗證
- 服務接口API限流 Rate Limit
- php內核分析---內存管理(一)
- PHP內存泄漏問題解析
- 【代碼片-1】 MongoDB與PHP -- 高級查詢
- 【代碼片-1】 php7 mongoDB 簡單封裝
- php與mysql系統中出現大量數據庫sleep的空連接問題分析
- 解決crond引發大量sendmail、postdrop進程問題
- PHP操作MongoDB GridFS 存儲文件,如圖片文件
- 淺談php安全
- linux上keepalived+nginx實現高可用web負載均衡
- 整理php防注入和XSS攻擊通用過濾