POST TIME:2017-11-13 00:19
使用 MySQL 數據庫的站點,當訪問連接數過多時,就會出現 "Too many connections" 的錯誤。出現這種錯誤有兩種情況,一種是網站訪問量實在太大,服務器已經負擔不起,此時就應該考慮負載均衡或者其它減少服務器壓力的辦法。另一種情況就是 MySQL 的最大連接數設置得太小,當訪問量稍大就出現連接過多的錯誤。win7下配置PHP+Apache+Mysql運行環境
MySQL 默認的最大連接數為 100,可以在 mysql 客戶端使用以下命令查看
mysql> show variables like 'max_connections';
此命令將得到類似以下的輸出結果:
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 2000 |
+-----------------+-------+
1 row in set (0.00 sec)
要對 mysql 的最大連接數進行修改,只需要在 my.cnf 配置文件里面修改 max_connections 的值,然后重啟 mysql 就行。如果 my.ini 文件中沒有找到 max_connections 條目,可自行添加以下條目
max_connections = 200
方法一: 02 03進入MySQL安裝目錄打開MySQL配置文件my.ini或my.cnf查找max_connections=100修改為max_connections=1000服務里重起MySQL即可 04 05方法二: 06 07MySQL最大連接數默認是100客戶端登錄: 08 09MySQL-uusername-ppassword 10 11設置新的MySQL最大連接數為200: 12 13MySQL>setGLOBALmax_connections=200 14 15顯示當前運行的Query: 16 17MySQL>showprocesslist 18 19顯示當前狀態: 20 21MySQL>showstatus 22 23退出客戶端:MySQL>exit 24 25查看當前MySQL最大連接數:MySQLadmin-uusername-ppasswordvariables 26 27方法三: 28 29以centos4.4下面的MySQL5.0.33手工編譯版本為例說明: 30 31vi/usr/local/MySQL/bin/MySQLd_safe 32 33找到safe_MySQLd編輯它,找到MySQLd啟動的那兩行,在后面加上參數: 34 35-Omax_connections=1500 36 37具體一點就是下面的位置: 38 39用紅字特別說明: 40 41then$NOHUP_NICENESS$ledir/$MySQLD 42$defaults--basedir=$MY_BASEDIR_VERSION 43--datadir=$DATADIR$USER_OPTION 44--pid-file=$pid_file 45--skip-external-locking 46-Omax_connections=1500 47>>$err_log2>&1else 48eval"$NOHUP_NICENESS$ledir/$MySQLD 49$defaults--basedir=$MY_BASEDIR_VERSION 50--datadir=$DATADIR$USER_OPTION 51--pid-file=$pid_file 52--skip-external-locking$args 53-Omax_connections=1500>> 54$err_log2>&1" 55 56保存。 57 58#serviceMySQLdrestart 59#/usr/local/MySQL/bin/MySQLadmin-uroot-pvariables 60 61輸入root數據庫賬號的密碼后可看到 62 63max_connections1500即新改動已經生效。 64 65還有一種方法, 66 67修改原代碼: 68 69解開MySQL的原代碼,進入里面的sql目錄修改MySQLd.cc找到下面一行: 70 71{"max_connections",OPT_MAX_CONNECTIONS, 72"Thenumberofsimultaneousclientsallowed.",(gptr*)&max_connections, 73(gptr*)&max_connections,0,GET_ULONG,REQUIRED_ARG,100,1,16384,0,1, 740}, 75 76把它改為: 77 78{"max_connections",OPT_MAX_CONNECTIONS, 79"Thenumberofsimultaneousclientsallowed.",(gptr*)&max_connections, 80(gptr*)&max_connections,0,GET_ULONG,REQUIRED_ARG,1500,1,16384,0,1, 810}, 82 83存盤退出,然后./configure;make;makeinstall可以獲得同樣的效果。以上的相關內容就是對修改MySQL最大連接數的3種方法的介紹,望你能有所收獲。
最近網站出現 User 數據庫名稱 has already more than 'max_user_connections' active connections 的報錯,網站癱瘓。有必要研究下這個問題。
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獲取一次數據之后就直接調用:
1 | mysql_free_result(m_result); |
2 | mysql_close(m_Database); |
但是有兩個問題:
當使用長連接時(即connect之后一直不close),如果最后會調用mysql_close,需不需要每次都調用mysql_free_result呢?
當mysql_close調用之后,m_result的數據是否還可以用。
先說一下結論:
必須每次調用。因為經過測試,每次mysql_store_result的指針都是不同的,可見并不是共享了同一塊buf。
還是可以使用。經過valgrind掃描,只調用mysql_close的掃描結果是:
1 | ==9397== 16,468 (88 direct, 16,380 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 5 |
2 | ==9397== at 0x40219B3: malloc (vg_replace_malloc.c:195) |
3 | ==9397== by 0x8053EA2: my_malloc (in /data/home/dantezhu/appbase/application/platform/openqqcom/share/db_openright/test/test) |
4 | ==9397== by 0x806D314: mysql_store_result (in /data/home/dantezhu/appbase/application/platform/openqqcom/share/db_openright/test/test) |
5 | ==9397== by 0x804BB04: CMySQLCppClient::Result(st_mysql_res*&) (mysql_cpp_client.cpp:127) |
6 | ==9397== by 0x804AB58: CDBOpenRight::GetUinsByApp(unsigned int, std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >&) (db_openright.cpp:58) |
7 | ==9397== by 0x8049F10: main (test.cpp:27) |
相關文章推薦:
1.dedecms搬家遠程附件 DedeTag Engine Create File False等N多問題
2.php連接mssql的方法 怎樣實現php連接mssql
3.mysql group by分組取每組前幾條記錄加order by排序
4.php+mysql實現無限級分類