什么是長連接?
其實長連接是相對于通常的短連接而說的,也就是長時間保持客戶端與服務端的連接狀態。
通常的短連接操作步驟是:
連接-》數據傳輸-》關閉連接 ;
而長連接通常就是:
連接-》數據傳輸-》保持連接-》數據傳輸-》保持連接-》…………-》關閉連接 ;
這就要求長連接在沒有數據通信時,定時發送數據包,以維持連接狀態,短連接在沒有數據傳輸時直接關閉就行了
什么時候用長連接,短連接?
長連接主要用于在 少數 客戶端與服務端的 頻繁 通信,因為這時候如果用短連接頻繁通信常會發生Socket出錯,并且頻繁創建Socket連接也是對資源的浪費。
但是對于服務端來說,長連接也會耗費一定的資源,需要專門的線程(unix下可以用進程管理)來負責維護連接狀態。
總之,長連接和短連接的選擇要視情況而定。
?
首先,如果使用了長連接而長期沒有對數據庫進行任何操作,那么在timeout值后,mysql server就會關閉此連接,而客戶端在執行查詢的時候就會得到一個類似于“MySQL server has gone away“這樣的錯誤。
在使用mysql_real_connect連接數據庫之后,再使用mysql_options( &mysql, MYSQL_OPT_RECONNECT, … ) 來設置為自動重連。這樣當mysql連接丟失的時候,使用mysql_ping能夠自動重連數據庫。如果是在mysql 5.1.6之前,那么則應在每次執行完real_connect 之后執行mysql_options( &mysql, MYSQL_OPT_RECONNECT, … ) ,如果是mysql 5.1.6+,則在connect之前執行一次就夠了。
?
查看mysql連接數
mysqladmin -uroot -p? processlist
實際的測試中我發現,當設置了MYSQL_OPT_RECONNECT為1時,超時后再查看processlist,則自動建立的連接不在列表中,但事實上連接確實建立并被使用了。
?
在MYSQL的默認設置中,如果一個數據庫連接超過8小時沒有使用(閑置8小時),服務器將斷開這條連接,后續在該連接上進行的查詢操作都將失敗。網絡上對該問題的描述非常多。也提供了相應的解決辦法。我在這里提一些我自己的看法。
解決辦法一:修改MYSQL服務器的配置參數
道理非常簡單,MYSQL的默認設置是在數據庫連接超過8小時沒有使用后將其斷開,如果我們將這個時間改成更大的數值,那么連接超時所需的時間就會更長,也就意味著更不容易超時。 網絡上提供的修改方法一般是修改/etc/my.cnf,在這個文件中添加一行wait_timeout=你需要設置的超時時間 。實際上有一種比較簡單的方法來修改這個參數:
首先作為超級用戶登錄到MYSQL,注意必須是超級用戶,否則后面會提示沒有修改權限。然后輸入
show global variables like 'wait_timeout';
回車執行后顯示目前的超時時間:
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 28800 |
+---------------+-------+
1 row in set (0.00 sec)
上面顯示的是默認的超時時間,即8個小時(單位是秒)。現在重新設置該參數,例如我們要將超時時間設置成10個小時,可以輸入:
set global wait_timeout=36000;
回車執行,顯示:
Query OK, 0 rows affected (0.00 sec)
表示設置成功,可以重新使用show global variables like 'wait_timeout'來驗證。
這種方法比較直觀,而且設置的參數立即生效。 但如果/etc/my.cnf中沒有配置,則重啟服務后,global變量會從/etc/my.cnf中讀取新的變量值。
?
下邊是一段示例代碼:
if(!mysql_real_connect(&logdb, my_hostname, my_user, my_password, my_dbname, my_port, my_sock, 0)){?
??????? ast_log(LOG_ERROR, "Failed to connect to mysql database %s on %s.\n", my_dbname, my_hostname);?
??????? use_mysql = 0;?
} else {?
?????? char value = 1;?
?????? mysql_options(&logdb, MYSQL_OPT_RECONNECT, (char*)&value);?
??????? use_mysql = 1;?
}
?
?
?
?
譬如 HTTP 的 Connection-alive 如果為 close,則 server 收到一個 request 并發送完一個 response 之后就會主動關閉連接,這就是短連接;如果 Connection-alive keep-alive 的話可以在一個 tcp 連接中交換多次對話。是這個定義?那就只是個程序結構設計問題了。
?
長連接短連接只是一個概念性的問題,只要知道其概念,不是一個特殊的東西:
長連接:系統通訊連接建立后就一直保持。
短連接:只有系統需要相互發消息連接才建立(客戶端發起),請求消息得到響應后連接關閉;
通訊實體間使用長連接,一般還需要定義心跳消息,定期發送來檢測系統間鏈路是否異常,每隔一定時間發送一次心跳,如果一定次數沒有收到心跳消息,這認為此連接出現問題,需要斷開連接重新建立。
具體心跳消息的格式,以及發送間隔,以及多少次沒有收到心跳就認為鏈路異常,以及數據部是否算作心跳消息(有的系統如果接收到數據包則會清除心跳計時器也就相當于系統中的數據包也算作心跳消息);這個需要兩端進行協商。比如GSM常用的短消息中心和其他網絡實體互連的SMPP協議,要求建立的就是長連接.
所以長短連接只是一個概念問題長短連接的socket,就是使用普通的socket函數,沒有什么特殊的。
PHP在連結MYSQL時有兩個FUNCTION
CONNECT與PCONNECT
這兩個函式的差別在哪裡?
一般的標準答案都是:
PCONNECT是持續性的連接,PHP會重複使用已經存在的資料庫連線
?
但是再追問下去,能說得出來的人就少了許多
常見的疑問有:
什麼時候要用CONNECT什麼時候用PCONNECT?
mysql_close何時使用?
為什麼DATABASE上有一堆SLEEP的PROCESS?
明明用PCONNECT為何每次RESOURCE ID都不同?
先回歸到最簡單的解釋,pconnect會去檢查是否有已經存在的資料庫連線。
若有,就使用舊的連線;若無,就新開啟一個連線
但是這裡所說得檢查連線,是指這一個APACHE行程所開啟的資料庫連線
而不是這一臺WEB SERVER所開啟的資料庫連線。
一臺WEB SERVER上可能有上百個APAHE行程(2.0預設最大150個)
也就是說 在最大情況下可能會有上百個PCONNECT造成的資料庫連線
(實際上會遠少於此)
所以同樣使用PCONNECT是會出現不同RESOURCE ID的
因為他可能是在不同行程上面執行
而PCONNECT是不會在查詢完成後就關閉,而是會等待一定時間
這個時間可以由MYSQL上的wait_timeout設定
而且mysql_close並無法關閉pconnect所開啟的連線,只能關閉connect所開啟的資料庫連線。當然如果沒有CLOSE在經過TIMEOUT時間之後也是會被DB DROP掉。
PCONNECT必須要小心使用,在寫的不好的CODE中,會殘留一大批的DATABASE CONNECTION。最大值可以這樣計算
每臺SERVER的APACHE行程數 * 所有WEB SERVEWR數量
當然不需要我來提醒,每個連線都會消耗DB的CPU TIME與MEMORY
寫WEB CODE時,不論使用何種語言,有兩點一定要再動手寫之前先有答案
一是,要從DATABASE抓取什麼資料
二是,要傳送什麼資料到USER端
(其實這也不只用於WEB)
DATABASE的連線是很慢的,能夠一次抓取完所需的資料,就不要分兩次
數據庫連接池由數據庫管理器提供。與連接語言無關。
php 提供了 pconnect 的機制, 可以實現連接池的功能 .
對於???mysql , mysql_pconnect 函數就可以實現 :
?數據庫連接使用完畢後, 並不釋放, 而是留在系統中, 下一次調用 mysql_pconnect 連接數據庫時, 首先檢查是否有空閒的連接未被使用, 如果有, 則使用這個連接, 而不是進行連接數據庫的操作, 從而節省系統開銷 .
?
1.數據庫連接池的工作機制是什么?它怎么提高數據的訪問速度呢???
---------------------------------------------------------------?
連接池的作用主要是節省打開數據庫的時間。??
由于打開數據庫連接比較耗時,所以連接池機制預先打開N個數據庫連接,把它們緩存起來,當需要使用數據庫的時候就直接使用這些已經打開的連接,從而節省了 時間。
創建新的對象并初始化的操作,可能會消耗 很多的時間。在這種對象的初始化工作包含了一些費時的操作(例如,從一臺位于20,000千米以外的主機上讀出一些數據)的時候,尤其是這樣。在需要大量 生成這樣的對象的時候,就可能會對性能造成一些不可忽略的影響。要緩解這個問題,除了選用更好的硬件和更棒的虛擬機以外,適當地采用一些能夠減少對象創建 次數的編碼技巧,也是一種有效的對策。對象池化技術(Object??Pooling)就是這方面的著名技巧.??
對象池化的基本思路是:將用過的對象保存起來,等下一次需要這種對象的時候,再拿出來重復使用,從而在一定程度上減少頻繁創建對象所造成的開銷。用于充當 保存對象的“容器”的對象,被稱為“對象池”(Object?Pool,或簡稱Pool)。??
數據庫連接pool是專門保存和管理數據庫連接的pool.??
恰當地使用對象池化技術,可以有效地減少對象生成和初始化時的消耗,提高系統的運行效率。??
采用對象池化的本意,是要通過減少對象生成的次數,減少花在對象初始化上面的開銷,從而提高整體的性能。然而池化處理本身也要付出代價,因此,并非任何情 況下都適合采用對象池化。????
基本上,只在重復生成某種對象的操作成為影響性能的關鍵因素的時候,才適合進行對象池化。如果進行池化所能帶來的性能提高并不重要的話,還是不采用對象池 化技術,以保持代碼的簡明,而使用更好的硬件和更棒的虛擬機來提高性能為佳。????
恰當地使用對象池化,可以有效地降低頻繁生成某些對象所造成的開銷,從而提高整體的性能。而借助Jakarta?Commons??Pool組件,可以有效地減少花在處理對象池化上的工作量,進而,向其它重要的工作里,投入更多的時間和精力。
數據庫連接池的原理:
J2EE服務器啟動時會建立一定數量的池連接,并一直維持不少于此數目的池連接。
客戶端程序需要連接時,池驅動程序會返回一個未使用的池連接并將其表記為忙。
如果當前沒有空閑連接,池驅動程序就新建一定數量的連接,新建連接的數量有配置參數決定。
當使用的池連接調用完成后,池驅動程序將此連接表記為空閑,其他調用就可以使用這個連接。
?
1.長連接?
Client方與Server方先建立通訊連接,連接建立后不斷開,然后再進行報文發送和接收。
2.短連接?
Client方與Server每進行一次報文收發交易時才進行通訊連接,交易完畢后立即斷開連接。此種方式常用于一點對多點通訊,比如多個Client連接一個Server.
?
?
?
短連接常見于大客戶情況 如WEB服務器如果每個連接都使用長連接 那么每個客戶都保留一個socket?系統資源耗費很大 。
長連接則是多用于操作頻繁情況每個TCP連接都需要三步握手 這需要時間 如果每個操作都是先連接 再操作的話那么處理速度會降低很多 所以每個操作完后都不斷開 下次處理時直接發送數據包就OK了 不用建立TCP連接。
另外還有同步操作和異步操作,同步操作指上一個操作返回結果后才能發下一個操作的數據包;異步操作指先把所有的操作數據包發完后 再等待它們的返回結果。相比較看, 異步操作速度快 特別是在每個包處理方法獨立的情況下 。
上面只是一個參考 最后要使用哪種類型還是決定于你。如聯通的短信協議就是 連接后可以發送多個短信包 但如果一段時間(如60s)沒有操作 那么連接就會被關閉。
?
?
?
?
數據庫永久連接
永久的數據庫連接是指在腳本結束運行時不關閉的連接。當收到一個永久連接的請求時。PHP 將檢查是否已經存在一個(前面已經開啟的)相同的永久連接。如果存在,將直接使用這個連接;如果不存在,則建立一個新的連接。所謂“相同”的連接是指用相同的用戶名和密碼到相同主機的連接。?
對 web 服務器的工作和分布負載沒有完全理解的讀者可能會錯誤地理解永久連接的作用。特別的,永久連接不會在相同的連接上提供建立“用戶會話”的能力,也不提供有效建立事務的能力。實際上,從嚴格意義上來講,永久連接不會提供任何非永久連接無法提供的特殊功能。?
為什么??
這和 web 服務器工作的方式有關。web 服務器可以用三種方法來利用 PHP 生成 web 頁面。?
第一種方法是將 PHP 用作一個“外殼”。以這種方法運行,PHP 會為向 web 服務器提出的每個 PHP 頁面請求生成并結束一個 PHP 解釋器線程。由于該線程會隨每個請求的結束而結束,因此任何在這個線程中利用的任何資源(例如指向 SQL 數據庫服務器的連接)都會隨線程的結束而關閉。在這種情況下,使用永久連接不會獲得任何地改變――因為它們根本不是永久的。?
第二,也是最常用的方法,是把 PHP 用作多進程 web 服務器的一個模塊,這種方法目前只適用于 Apache。對于一個多進程的服務器,其典型特征是有一個父進程和一組子進程協調運行,其中實際生成 web 頁面的是子進程。每當客戶端向父進程提出請求時,該請求會被傳遞給還沒有被其它的客戶端請求占用的子進程。這也就是說當相同的客戶端第二次向服務端提出請求時,它將有可能被一個不同的子進程來處理。在開啟了一個永久連接后,所有請求 SQL 服務的后繼頁面都能夠重新使用這個已經建立的 SQL Server 連接。?
最后一種方法是將 PHP 用作多線程 web 服務器的一個插件。目前 PHP 4 已經支持 ISAPI、WSAPI 和 NSAPI(在 Windows 環境下),這些使得 PHP 可以被用作諸如 Netscape FastTrack (iPlanet)、Microsoft's Internet Information Server (IIS) 和 O'Reilly's WebSite Pro 等多線程 web 服務器的插件。永久連接的行為和前面所描述的多過程模型在本質上是相同的。注意 PHP 3 不支持 SAPI。?
如果永久連接并沒有任何附加的功能,那么使用它有什么好處??
答案非常簡單――效率。當客戶端對 SQL 服務器的連接請求非常頻繁時,永久連接將更加高效。連接請求頻繁的標準取決于很多因素。例如,數據庫的種類,數據庫服務和 web 服務是否在同一臺服務器上,SQL 服務器如何加載負載等。但我們至少知道,當連接請求很頻繁時,永久連接將顯著的提高效率。它使得每個子進程在其生命周期中只做一次連接操作,而非每次在處理一個頁面時都要向 SQL 服務器提出連接請求。這也就是說,每個子進程將對服務器建立各自獨立的永久連接。例如,如果有 20 個不同的子進程運行某腳本建立了永久的 SQL 服務器永久連接,那么實際上向該 SQL 服務器建立了 20 個不同的永久連接,每個進程占有一個。?
注意,如果永久連接的子進程數目超過了設定的數據庫連接數限制,系統將會產生一些缺陷。如果數據庫的同時連接數限制為 16,而在繁忙會話的情況下,有 17 個線程試圖連接,那么有一個線程將無法連接。如果這個時候,在腳本中出現了使得連接無法關閉的錯誤(例如無限循環),則該數據庫的 16 個連接將迅速地受到影響。請查閱使用的數據庫的文檔,以獲取關于如何處理已放棄的及閑置的連接的方法。
?
?
?
?
?
?
應用程序和數據庫建立連接,如果超過?wait_timeout?(
默認28000秒8小時
)?應用程序不去訪問數據庫,連接一直處于空閑狀態,那么MySQL就會自動關閉該連接?,如果再在該連接上執行查詢操作,就會發生MySQL server has gone away錯誤。
wait_timeout?
服務器在關閉連接之前在一個連接上等待行動的秒數,默認數值是28800,即如果沒有事情發生,服務器在?8個小時后關閉連接。
??
嘗試解決辦法:
<1>.這是由于超時時間?wait_timeout?過短導致,所以修改它的值即可。打開MySQL安裝目錄下的?mysql.ini,在文件中添加一行配置項?wait_timeout=1000000?即可。(默認沒有此選項,需要手動的添加)
該方法可行。
?
<2>.在代碼中設置自動重連選項,
m_connection.set_option( new?mysqlpp::ReconnectOption(true) );
?
然后在發生?MySQL server has gone away錯誤?的時候?調用?Connection::ping()方法,該函數會檢查對服務器的連接是否正在工作,必要時重新連接,但經過測試后發現,這種方法不起作用。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
