PHP Conference Japan 2024

mysql_pconnect

(PHP 4, PHP 5)

mysql_pconnect開啟至 MySQL 伺服器的持續性連線

警告

此擴充功能在 PHP 5.5.0 中已棄用,並在 PHP 7.0.0 中移除。應改用 MySQLiPDO_MySQL 擴充功能。另請參閱 MySQL:選擇 API 指南。此函式的替代方案包括

描述

mysql_pconnect(
    字串 $server = ini_get("mysql.default_host"),
    字串 $username = ini_get("mysql.default_user"),
    字串 $password = ini_get("mysql.default_password"),
    整數 $client_flags = 0
): 資源

建立與 MySQL 伺服器的持續性連線。

mysql_pconnect() 的行為與 mysql_connect() 非常相似,但有兩個主要差異。

首先,在連線時,函式會先嘗試尋找一個已使用相同主機、使用者名稱和密碼開啟的(持續性)連結。如果找到,則會傳回該連結的識別碼,而不是開啟新的連線。

其次,當腳本執行結束時,與 SQL 伺服器的連線不會關閉。相反地,該連結將保持開啟以供未來使用(mysql_close() 不會關閉由 mysql_pconnect() 建立的連結)。

因此,這種連結稱為「持續性」。

參數

server

MySQL 伺服器。它也可以包含埠號。例如 "hostname:port" 或本機 socket 的路徑,例如 localhost 的 ":/path/to/socket"。

如果 PHP 指令 mysql.default_host 未定義(預設值),則預設值為 'localhost:3306'

username

使用者名稱。預設值為擁有伺服器程序的 使用者名稱。

password

密碼。預設值為空密碼。

client_flags

client_flags 參數可以是以下常數的組合:128(啟用 LOAD DATA LOCAL 處理)、MYSQL_CLIENT_SSLMYSQL_CLIENT_COMPRESSMYSQL_CLIENT_IGNORE_SPACEMYSQL_CLIENT_INTERACTIVE

傳回值

成功時傳回 MySQL 持續性連結識別碼,失敗時傳回 false

注意事項

注意:

請注意,這類連結只有在使用 PHP 的模組版本時才能運作。請參閱持續性資料庫連線一節以取得更多資訊。

警告

使用持續性連線可能需要對 Apache 和 MySQL 設定進行一些調整,以確保您不超過 MySQL 允許的連線數。

參見

新增註解

使用者貢獻的註解 28 則註解

seawyvern at gmail dot com
14 年前
(使用 PHP v5.3.2)
這可能會幫助其他遇到類似問題的人。我偶爾會在我的 apache 錯誤記錄中收到此錯誤

PHP 警告:mysql_pconnect():MySQL 伺服器已消失

似乎 mysql_pconnect() 傳回的持續性連線已逾時,且 mysql_pconnect() 未偵測到。為了解決此問題,我新增了一些程式碼,使用 mysql_ping() 檢查這種情況,如果發生這種情況,則向 mysql_pconnect() 要求另一個連線。似乎結合使用 mysql_ping() 檢查逾時,並使用 mysql_pconnect() 重新要求連線,會導致原始連線重新連線,或強制 mysql_pconnect() 辨識到連線已逾時並要求新的連線。mysql_ping() 的文件指出,如果偵測到逾時,它會強制重新連線,但是文件頁面上的註解指出此功能已停用一段時間。總之,這是我使用的程式碼,希望它有所幫助

$dbConnection = mysql_pconnect( $myHostname, $myUsername, $myPassword );

if ( !mysql_ping( $dbConnection ) )
{
$dbConnection = mysql_pconnect( $myHostname, $myUsername, $myPassword );
}
fate_amendable_to_changeNOSPAM at yahoo dot com
22 年前
若要告知 mysql_pconnect 連接到非預設埠上的 mysql,請使用冒號 - 例如

mysql_pconnect("127.0.0.1:4444", "user", "pass")

會連線到埠 4444 上的 localhost

(對於 ssh 通道等很有用)
script_this at yahoo dot com
21 年前
回應用戶 uthayakutty76 at yahoo dot com 的
2003 年 6 月 30 日 12:31 的文章

-----------------------------------------------------------
...問題是與 MySQL 的連線
伺服器中斷得非常快,或者根本沒有
連線。我們發現當使用
伺服器的網域而不是「localhost」時會發生問題.....
發生問題.....
-----------------------------------------------------------

請嘗試在 my.cnf 中將 mysql 的 wait_timeout 變數設定為
非常高,因此連線永遠不會閒置
那麼長時間。真的很可笑,但它適用於
localhost 或遠端資料庫伺服器,而
localhost 解決方案僅在資料庫是本機時才有效,我
認為。
mightye (at) mightye (dot) org
20 年前
通常您不希望使用 mysql_pconnect。此函式是為連線到資料庫具有較高負擔的環境設計的。在典型的 MySQL / Apache / PHP 環境中,Apache 將建立許多閒置等待 Web 請求分配給它們的子程序。每個子程序都會開啟並保留自己的 MySQL 連線。因此,如果您的 MySQL 伺服器限制為 50 個連線,但 Apache 保持執行 50 個以上的子程序,則每個子程序都可以保留與 MySQL 伺服器的連線,即使它們處於閒置狀態 (閒置的 httpd 子程序不會將其 MySQL 連線借給其他 httpd 子程序,它們會保留自己的連線)。因此,即使您只有幾個頁面實際連線到忙碌網站上的 MySQL,您也可能會用完連線,而且這些連線實際上都未使用。

一般而言,除非建立連線需要很長時間,否則請使用 mysql_connect() 連線到 MySQL。
david at hundsness dot com
16 年前
以下是不要使用持續性連線的重要原因摘要

* 當您鎖定表格時,通常會在連線關閉時解除鎖定,但是由於持續性連線不會關閉,因此您意外保留鎖定的任何表格都將保持鎖定,而解除鎖定的唯一方法是等待連線逾時或終止該程序。交易也會發生相同的鎖定問題。(請參閱下方 2002 年 4 月 23 日和 2003 年 7 月 12 日的註解)

* 通常,當連線關閉時,會捨棄暫時表格,但是由於持續性連線不會關閉,因此暫時表格並不是那麼暫時的。如果您未在完成時明確捨棄暫時表格,則該表格將已經存在,供重複使用相同連線的新客戶使用。設定會話變數也會發生相同的問題。(請參閱下方 2004 年 11 月 19 日和 2006 年 8 月 7 日的註解)

* 如果 PHP 和 MySQL 位於同一伺服器或本機網路上,則連線時間可能可以忽略不計,在這種情況下,持續性連線沒有優勢。

* Apache 在處理持續連線時效果不佳。當它收到來自新客戶端的請求時,它傾向於產生一個新的子程序,而不是使用已經開啟持續連線的可用子程序。這導致過多的程序處於休眠狀態,浪費資源,並且在達到最大連線數時導致錯誤,此外也抵銷了持續連線的任何好處。(請參閱 2004 年 2 月 3 日的以下評論,以及 http://devzone.zend.com/node/view/id/686#fn1 的註腳)
matt *at* roughest *dot* net
20 年前
在執行多個 MySQL 伺服器的機器上使用持續連線時要非常小心。您必須指定正確的 Socket 路徑,否則 PHP 將會重複使用連線,而不管它們連線到哪個伺服器。也就是說,它會看到一個具有匹配參數的開啟連線並使用它,即使該連線實際上是給不同的伺服器使用。
spam at vrana dot cz
21 年前
請注意,如果在伺服器上的不同腳本中對 mysql_pconnect() 使用不同的參數,PHP 可以為每個程序中每組參數建立單一的持續連線,直到達到每個程序的 mysql.max_persistent (PHP 指令) 上限。因此,即使您的 Apache MaxClients 指令設定小於 MySQL 的 max_connections 指令,您也可能很容易收到「Too many connections」的 MySQL 錯誤。

如果 mysql.max_persistent 設定為 -1(無限制,預設值)以外的值,超過此限制的連線將會被默默拒絕,因此請謹慎使用。

解決方案:對於可能具有無限組連線參數的伺服器,使用 mysql.allow_persistent=Off 禁止持續連線。
3ch0
18 年前
當您在大型網站上使用遠端資料庫伺服器時,建議使用 pconnect。特別是 MySQL,與每分鐘建立 1000 個連線相比,使用 1 個開啟連線會更穩定 =)
pulstar at mail dot com
21 年前
當我使用 mysql_pconnect 連接到遠端伺服器並使用 MYSQL_CLIENT_COMPRESS 標誌時,遇到了一些問題。有時它可以連線,但很多時候會出現錯誤
Warning: mysql_pconnect(): Unknown database 'XXXXX'

如果您遇到相同的問題,請嘗試改用 mysql_connect。對我來說運作良好。每次重新載入頁面時,腳本都需要較長的時間重新連線,但它將以壓縮方式傳輸資料。這比透過網際網路傳送純文字資料更安全一點,並且在傳輸大量資料時也更快。
Ron
19 年前
這裡有一個很棒的小類別,它可以使用持續連線在多個複製的 MySQL 伺服器實例之間進行負載平衡,並自動從池中移除失敗的 MySQL 伺服器。

您只會將此用於查詢,絕不會用於插入/更新/刪除,除非您有多主機情況,其中對任何資料庫伺服器的更新會自動複製到其他伺服器(我不確定 MySQL 是否可以做到這一點)。

使用此類別,您可以像這樣獲得與 MySQL 伺服器的連線
$con = MySQLConnectionFactory::create();

這是類別(您需要為您的組態自訂 $SERVERS 陣列 -- 請注意,您可能會對所有伺服器使用相同的用戶名、密碼和資料庫,僅更改主機名稱,但您並非必須使用相同的)。

<?php
class MySQLConnectionFactory {
static
$SERVERS = array(
array(
'host' => 'myHost1',
'username' => 'myUsername1',
'password' => 'myPassword1',
'database' => 'myDatabase1'),
array(
'host' => 'myHost2',
'username' => 'myUsername1',
'password' => 'myPassword2',
'database' => 'myDatabase2')
);

public static function
create() {
// 找出哪些連線已開啟,自動開啟任何失敗或尚未開啟但可以(重新)建立的連線。
$cons = array();
for (
$i = 0, $n = count(MySQLConnectionFactory::$SERVERS); $i < $n; $i++) {
$server = MySQLConnectionFactory::$SERVERS[$i];
$con = mysql_pconnect($server['host'], $server['username'], $server['password']);
if (!(
$con === false)) {
if (
mysql_select_db($server['database'], $con) === false) {
echo(
'無法選擇資料庫:' . mysql_error());
continue;
}
$cons[] = $con;
}
}
// 如果沒有伺服器回應,則擲回例外。
if (count($cons) == 0) {
throw new
Exception
('無法連線到任何資料庫伺服器 - 最後一個錯誤:' . mysql_error());
}
// 從活動連線列表中隨機挑選一個連線。
$serverIdx = rand(0, count($cons)-1);
$con = $cons[$serverIdx];
// 返回連線。
return $con;
}
}
?>
m at louislivi dot com
5 年前
SMProxy
基於 MySQL 協定和 Swoole 的 MySQL 資料庫連線池。
https://github.com/louislivi/SMProxy
shane
13 年前
新的 mysqlnd 函式庫取代了舊的 libmysql,應該可以讓連線消失成為過去。它會在嘗試使用連線之前刷新連線(變更使用者或 ping)。(它還使用更少的記憶體,並且通常具有更好的效能。)我只在 mysqli 中嘗試過,但原生擴充也使用它。它適用於 PHP >= 5.3,MySQL >= 4.1。
JM
16 年前
如果您收到一則關於 /var/mysql/mysql.sock 失敗的錯誤訊息,請嘗試變更 php.ini,使 mysql.default_socket=/tmp/mysql.sock
federico dot chiesa at tiscali dot it
20 年前
在 MySQL 上使用持續連線和暫存表時要非常小心:在 MySQL 中,暫存表僅對目前的連線可見,但如果您有持續連線,則暫存表應該對共享相同持續連線的所有人可見。這可能會導致嚴重的麻煩。我建議在使用持續連線時使用完全隨機的暫存表名稱,以避免嚴重的問題。
markunderscoreconnollyatacmdotorg
20 年前
我想評論來自 dfischer at qualcomm dot com 的文章,該文章建議在多個應用程式調用中跨越交易,以防有人大膽嘗試。

我假設使用的表格類型是支援交易的其中一種,例如 InnoDB 或 BerkeleyDB。

首先,這是否可行是一個問題。為了讓它完全運作,交易環境必須在透過 Web 伺服器的所有 php 程式碼調用中保持一致。閱讀 https://php.dev.org.tw/manual/en/features.persistent-connections.php 的描述,維持交易環境充其量是一種巧合。如果發現這偶爾確實有效,並且了解此行為的後果,將會很有趣。如果我剛好取得您的連線,而我的動作是取消,您的更新可能會消失。

其次,如果這種情況確實有效(偶爾或總是),那麼底層資料庫管理幾乎是開放式的交易,就會產生效能影響。幾個長時間執行的交易可能會在短時間內消耗大量資源,並可能增加並行衝突的可能性。如果 mysql_pconnect 行為是在 php 處理結束時保持交易開啟,那麼在使用 mysql_pconnect 時最好不要定義交易。而且,永遠沒有被程式碼關閉的交易(使用者去吃午餐並被公車撞到)可能會佔用資源很長一段時間(可能直到復健之後)。

因此,即使這種方案可能有效,這也不是一個好主意。交易應在使用者請求處理結束時提交或回滾。這允許 DBMS 正確管理資源使用,並防止壞事發生在好的資料上。如果 mysql_pconnect 與資料庫引擎的交易組件無法很好地協調,以便總是在處理請求結束時結束交易,那麼在任何使用 begin transaction 的地方都絕不應該使用 mysql_pconnect。
dfischer at qualcomm dot com
20 年前
如果您的交易跨越多個頁面,您也可以考慮使用 pconnect。例如,在我開發的應用程式中,我會在查詢選擇使用者計劃編輯的資料時開始交易。然後,在使用者按下提交按鈕並且資料已提交後,我會提交交易。

我不能簡單地使用 mysql_connect,因為連線會在頁面結束時終止,而且如果我沒有提交交易,它會自動回滾。
aaryal at foresightint dot com
20 年前
在 MySQL 運行於同一主機但使用多個埠口(多資料庫配置)的情況下,請勿使用 pconnect。PHP 中的連線池演算法顯然只以主機、使用者名稱和密碼作為鍵值,而不包含埠口。因此,如果您使用相同的主機、使用者名稱和密碼,但使用不同的埠口,您可能會獲得一個連線到與您要求的埠口不同的連線。
amn -at- frognet.net
21 年前
使用 mysql_pconnect 時請務必小心。如果您是託管在 ISP 上,他們可能不喜歡您使用多個持續的 MySQL 連線,因為這會長時間消耗資源。如果您的腳本崩潰,您的連線可能會長時間保持開啟。如果涉及到迴圈,您可能會不小心耗盡所有可用的連線。這可能會被 ISP 視為濫用,您可能會惹上麻煩。請先嘗試使用 mysql_connect。90% 的情況下,非持續的 mysql_connect 呼叫就能很好地解決問題。
david at acz dot org
22 年前
使用持續連線的 LOCK TABLES 時,您需要非常小心。如果腳本在執行 UNLOCK TABLES 之前終止,則表將保持鎖定狀態,並且很可能會掛起未來的腳本。這在錯誤報告中有所註明,但仍未反映在文件中:http://bugs.php.net/bug.php?id=7634
bartek at bulzak dot com
22 年前
在 Linux 下與 Apache 一起執行的 PHP 4.1.1 在處理持續的 MySQL 連線時似乎沒有執行所有必要的刷新。請自行嘗試。在 pconnect 會話中建立一個臨時表,加入多行(非唯一),選擇/顯示並刪除該表。現在多次重新載入您的腳本,您會看到您的結果不一致,即使您每次都建立一個新表並刪除它。

我使用 pconnect 時遇到過不少問題,建議您除非絕對必要,否則不要使用它。在這種情況下,請務必測試結果的一致性,特別是當您的查詢涉及臨時表或 MySQL 會話變數時。

Bartek Bulzak
David
15 年前
在我升級到 PHP 5.3 後,我幾乎每次從 Apache 伺服器發出的頁面請求都會開始出現「MySQL 伺服器已斷線」的錯誤。我嘗試了一些沒有效果的想法。這是解決方案:我將所有的 mysql_pconnect() 語句改為 mysql_connect()。它解決了這個問題。由於某些原因,PHP 5.3 不喜歡持續連線。
sasha at mysql dot com
24 年前
如果您需要關閉閒置的持續連線,請在 MySQL 中設定較低的 wait_timeout。
Sabyasachi Ruj
17 年前
如果您使用 mysql_pconnect(),並且假設 MySQL 伺服器為該用戶端建立了五個持續連線池。

現在 mysql_pconnect 可以返回其中任何一個。

因此,如果您期望 mysql_pconnect 始終返回相同的持續連線,情況並非如此。

因此,假設您在透過 mysql_pconnect 連線後執行了

set @aa=6;

在另一個頁面中,您又執行了 mysql_pconnect,並執行了

select @aa;

結果不一定會返回「6」!

因為第二個 mysql_pconnect 可以從該伺服器的連線池中取得另一個持續連線。
rudenko at id.com.ua
21 年前
您可以在 php 設定檔中設定指令 mysql.allow_persistent = Off 來解決持續連線的問題。嘗試建立持續連線 /mysql_pconnect()/ 的使用者將會連線到資料庫
使用非持續連線 /mysql_connect()/

如需更多資訊,請參閱「持續連線」部分的使用者註解。https://php.dev.org.tw/manual/en/features.persistent-connections.php
--
http://www.id.com.ua Ilya Rudenko
Nils Meyer nils at weiss-bescheid dot de
18 年前
在持續的 MySQL 連線上設定變數時請務必小心。範例
// 將結果字元集設定為 UTF8
mysql_query("SET SESSION character_set_results = 'UTF8'");

如果另一個腳本重複使用您的持續連線,它也會使用 UTF-8 字元集。這在 typo3 和 TemplaVoila 中造成了問題,它們從資料庫中讀取序列化的資料。資料以 UTF8 形式返回,但腳本預期使用 latin1,並出現序列化錯誤(「無法成功還原序列化範本物件。」)。這個問題特別棘手,因為它在某些請求上可以正常運作,而在其他請求上會崩潰 - 因為該變數並未在持續連線池中的所有連線上設定。

一個可能的解決方案是在之後將變數重設為其預設值
$ret = mysql_query("SHOW VARIABLES LIKE 'character_set_results'");
list($foo, $old_charset) = mysql_fetch_assoc($ret);
mysql_query("SET SESSION character_set_results = 'UTF8'");
// 執行一些精美的 utf8 操作
// ..

// 還原為舊編碼
mysql_query("SET SESSION character_set_results = '$old_charset'");

或者,就像先前所述,直接使用 mysql_connect(),這在大多數環境中更有意義,並且需要處理的事情更少(例如變數、交易、臨時表)。
tomek at 3kropki dot pl
19 年前
您可以設定 interactive_timeout 為較短的時間段(例如 20 秒),而不是使用 wait_timeout,這在 apache + mysql 環境中是比 wait_timeout 更好的解決方案。

若要了解有關 interactive_timeout 的更多資訊,請參閱 MySQL 文件。
rochlin at centralpets dot com
21 年前
請勿將交易(例如使用 InnoDB MySQL 表)與持續連線一起使用。如果您的腳本因任何原因停止或退出,您的交易將保持開啟狀態,並且您的鎖將保持開啟狀態。您必須重設 MySQL 才能釋放它們(據我所知)。它們不會像應該的那樣在錯誤時自動 ROLLBACK。當您重新啟動腳本時,您將獲得一個新的連線,因此您無法針對先前的腳本進行回滾或提交。任何具有開始交易、回滾或提交 SQL 語句的腳本都應使用常規(非持續)連線。似乎 PHP 應該在腳本退出(無論錯誤或其他)且未進行 COMMIT 時自動對任何開啟的交易發出 ROLLBACK。ZEND 的網站上有一個關於此的簡短說明。混合/搭配是可以的,因此您可以將持續連線用於讀取內容,但在有條件的情況下開啟新的常規連線(如果您必須更新,通常頻率較低)。
Tom
14 年前
與上述建議相反,持續連線適用於 fastCGI 管理的 CGI PHP,而非僅適用於模組版本。這是因為 fastCGI 會在請求之間保持 PHP 程序執行。在這種模式下,持續連線也很容易不受連線限制的影響,因為您可以設定 PHP_FCGI_CHILDREN << mysql 的 max_connections <<< Apache 的 MaxClients。這也能節省資源。
To Top