首頁  >  文章  >  後端開發  >  Nine Million Bicycles MySQL連線數超過限制的解決方法

Nine Million Bicycles MySQL連線數超過限制的解決方法

WBOY
WBOY原創
2016-07-29 08:46:05898瀏覽

max_user_connections 是 MySQL 使用者連線數的最大值設置,整段語句的意思是:伺服器的 MySQL 的最大連線數參數設定不足。解決方法:修改 MySQL 安裝目錄下 my.ini 或 my.cnf 檔案內的 max_user_connections 參數的數值,重新啟動 MySQL 伺服器。
但正常來說,MySQL預設的100個連線數是足夠的。我們需要從程序上去考慮。 MySQL的預設最大連線數為100(N),實際上給一般使用者使用只有N-1個,保留一個連線是留給超級管理員使用的,防止連線佔滿了不會把管理員也踢出來。很多網站在運作的時候都會出現連線數受限現象,我認為十之八九並非是網站的真實訪問量太大導致連接數超標,更多是因為我們在設計網站程式的時候採用了不合理的設計架構或資料結構所引起的。非正常連線超限可能原因如下(天緣即時歸納未必完整或無錯訥僅供參考):
類似人數、線上時間、瀏覽數等統計功能與主程式資料庫同屬一個資料空間時就很容易出現。
複雜的動態頁面尤其是使用者每次瀏覽都涉及到多資料庫或多表操作時候也很容易出現。
還有就是程式設計的不合理(例如複雜運算、等待等操作放置在資料庫互動行為中間進行),或是程式存在釋放BUG。
電腦硬體配置太低卻安裝太高版、太高配置的MySQL。
未採用快取技術。
資料庫未經最佳化或表格設計及其複雜。
等等一些原因,都會延長資料庫的資料互動時間或增加互動次數。所以,如果大家遇到這類問題,首先要考慮程式是否有BUG導致連線釋放失敗,再次就是考慮優化軟硬體。當然修改MySQL連線數也是軟體優化的操作方法之一,希望大家都能以學習的態度透過研究一下自身的原因來解決這個問題。如果實在是找不到原因,那就只好先修改連線數,暫緩定位真實原因了。
關於PHP的資料庫持久連接mysql_pconnect
PHP程式設計師應該都知道連接MySQL資料庫可以使用mysql_pconnect(永久連接)函數,使用資料庫永久連接可以提高效率,但是實際應用中資料庫永久連接往往會導致出現一些問題,通常的表現就是在大訪問量的網站上時常發生斷斷續續的無法連接數據庫的情況,出現類似"Too many connections in ..."的錯誤提示信息,重新啟動服務器又正常了,但過不了一會兒又出現同樣的故障。對於這些問題的成因,恐怕就不是每個人都能說清楚的了,雖然PHP文檔裡有一些相關資料,但是解釋的並不淺顯易懂,這裡我厚著臉皮試圖做一個簡單的討論,所述觀點不見得全都正確,歡迎大家回饋意見。
先看看資料庫永久連線的定義:永久的資料庫連線是指在腳本結束執行時不關閉的連線。當收到一個永久連線的請求時。 PHP 將檢查是否已經存在一個(前面已經開啟的)相同的永久連線。如果存在,將直接使用這個連接;如果不存在,則建立一個新的連接。所謂"相同"的連線是指用相同的使用者名稱和密碼到相同主機的連線。
PHP使用永久連接方式操作MySQL是有前提的:就是PHP必須安裝為多執行緒或多進程Web伺服器的插件或模組。最常見的形式是把PHP當作多進程Apache伺服器的一個模組。對於一個多進程的伺服器,其典型特徵是有一個父進程和一組子進程協調運行,其中實際生成Web頁面的是子進程。每當客戶端向父進程提出請求時,該請求會傳遞給尚未被其它的客戶端請求佔用的子進程。這也就是說當相同的客戶端第二次向服務端提出請求時,它將有可能被一個不同的子程序來處理。在開啟了一個永久連線後,所有不同子程序請求SQL服務的後繼頁面都能夠重新使用這個已經建立的 SQL伺服器連線。它使得每個子進程在其生命週期中只做一次連接操作,而非每次在處理一個頁面時都要向 SQL 伺服器提出連接請求。每個子進程將對伺服器建立各自獨立的永久連線。 PHP本身並沒有資料庫連線池的概念,但是Apache有進程池的概念, 一個Apache子進程結束後會被放回進程池, 這也就使得用mysql_pconnect打開的那個mysql連接資源可以不被釋放,而是依附在對應的Apache子程序上保存到了進程池中。於是在下一個連線請求時它就可以被重複使用。一切看起來似乎都很正常,但是在Apache並發訪問量大的時候,如果使用mysql_pconnect,會由於之前的Apache子進程佔用的MySQL連接沒有close, 很快使MySQL達到最大連接數,使得之後的請求可能得不到響應。
上面的部分文字是摘抄自PHP文檔,看起來可能還是有些文縐縐的不好理解,那麼我就用大白話再舉一個例子來說明問題:
假設Apache配置最大連接數為1000, MySQL配置最大連接數為100,當Apache伺服器接到200個並發訪問的時候,其中100個涉及到數據庫訪問,剩下的100個不涉及數據庫訪問,因為這個時候還不存在可用的數據庫連接,所以這裡面涉及到資料庫存取的100個並發會同時產生100個資料庫永久連接,達到了資料庫最大連接數,當這些操作沒有結束的時候,任何其他的連接都無法再獲得資料庫連接,當這些操作結束了,對應的連線會被放入進程池,此時Apache的進程池裡就有了200個空閒的子進程,其中100個是帶有資料庫連線的,由於Apache會為存取請求隨機的挑選空閒子進程,所以你得到的子進程很可能是不包含資料庫連接的那100個中的一個,而資料庫連接已經達到了最大值,你也不可能成功的建立新的資料庫連接,唉,你便只好不停的刷新頁面,哪個時候運氣好,碰巧分配到了帶有資料庫連接的子進程,才能正常瀏覽頁面。如果是大訪問量的網站來說,任何時候都可能存在大量的並發,所以瀏覽者可能就會不停的發現無法連接資料庫的現象了。
或許你會說,我們把Apache和MySQL的最大連線數調成一樣大不就可以了麼?是的,合理的調整這個最大連接數某種程度上會避免這個問題的發生,但是Apache和MySQL的負載能力是不同的,如果按照Apache的負載能力來設置,對於MySQL來說,這個最大連接數就偏大,會產生大量的MySQL資料庫永久連接,打個比方,就好像和平時代還要養活一個幾百萬的軍隊一樣,其開銷得不償失;而如果按照Mysql的負載能力設置,對於Apache來說,這個最大連結數就偏小,有點殺雞牛刀的感覺,無法發揮Apache的最大效率。
所以按照PHP手冊上的介紹,只適合在並發訪問不大的網站上使用數據庫永久連接,但對於一個並發訪問不大的網站來說,使用數據庫永久連接帶來的效率提高似乎沒有太大的意義,從這個角度來看,我覺得PHP中的資料庫永久連接基本上是一個雞肋的角色,如果你一定要使用資料庫連接池的概念,可以試試sqlrelay或Apache本身提供的mod_dbd,說不定會有驚喜。
關於mysql_free_result和mysql_close
之前用mysql的時候一直是在用短鏈接,調用mysql_store_result獲取一次數據之後就直接調用:

複製代碼 程式碼如下:


mysql_free_result(m_result);
mysql_close(m_Database);


但是有兩個問題:
使用長(即connect之後一直不close),如果最後會呼叫mysql_close,需不需要每次都呼叫mysql_free_result呢?
當mysql_close呼叫之後,m_result的資料是否還可以用。
先說一下結論:
必須每次呼叫。因為經過測試,每次mysql_store_result的指標都是不同的,可見並不是共享了同一塊buf。
還是可以使用。經過valgrind掃描,只呼叫mysql_close的掃描結果是:

複製代碼 代碼如下:


==9397== 16,468 (88 direct, 16,380 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 5
==9397== at 0x40219B3: malloc (vg_replace_malloc.c:195) ==9397== by 0x806D314: mysql_store_result (in /data/home/appezhu/app /platform/openqqcom/share/db_openright/test/test)
==9397== by 0x804BB04: CMySQLCppClient::Result(st_mysql_res*&) (mysql_c==_client.cpp:127) 380 月 3831327) , std::allocator >&) (db_openright.cpp:58)
==9397 == by 0x8049F10: main (test.cpp:27)


以後再慢慢研究。 。

以上就介紹了Nine Million Bicycles MySQL連線數超過限制的解決方法,包括了Nine Million Bicycles方面的內容,希望對PHP教學有興趣的朋友有所幫助。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn