2024年PHP开发者大会日本站

mysql_pconnect

(PHP 4, PHP 5)

mysql_pconnect打开到MySQL服务器的持久连接

警告

此扩展在PHP 5.5.0中已弃用,并在PHP 7.0.0中移除。应改用MySQLiPDO_MySQL扩展。另请参见MySQL:选择API指南。此函数的替代方法包括

描述

mysql_pconnect(
    string $server = ini_get("mysql.default_host"),
    string $username = ini_get("mysql.default_user"),
    string $password = ini_get("mysql.default_password"),
    int $client_flags = 0
): resource

建立到MySQL服务器的持久连接。

mysql_pconnect() 的行为与mysql_connect() 非常相似,但有两个主要区别。

首先,连接时,函数会首先尝试查找已经使用相同主机、用户名和密码打开的(持久)链接。如果找到,则会返回其标识符,而不是打开新的连接。

其次,当脚本执行结束时,与SQL服务器的连接不会关闭。相反,该链接将保持打开状态以供将来使用(mysql_close()不会关闭由mysql_pconnect()建立的链接)。

因此,这种类型的链接称为“持久”链接。

参数

服务器

MySQL服务器。它还可以包含端口号,例如“主机名:端口”或本地套接字的路径,例如“:/path/to/socket”(对于本地主机)。

如果PHP指令 mysql.default_host未定义(默认值),则默认值为'localhost:3306'

用户名

用户名。默认值为拥有服务器进程的用户名称。

密码

密码。默认值为空密码。

客户端标志

client_flags参数可以是以下常量的组合:128(启用LOAD DATA LOCAL处理)、MYSQL_CLIENT_SSLMYSQL_CLIENT_COMPRESSMYSQL_CLIENT_IGNORE_SPACEMYSQL_CLIENT_INTERACTIVE

返回值

成功时返回MySQL持久链接标识符,失败时返回false

备注

注意:

请注意,只有在使用模块版本的PHP时,此类链接才有效。有关更多信息,请参阅持久数据库连接部分。

警告

使用持久连接可能需要对Apache和MySQL配置进行一些调整,以确保不会超过MySQL允许的连接数。

参见

添加备注

用户贡献的备注 28条备注

9
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 );
}
9
fate_amendable_to_changeNOSPAM at yahoo dot com
22年前
要告诉mysql_pconnect连接到非默认端口的mysql,请使用冒号 - 例如

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

将连接到端口4444上的localhost

(对ssh隧道等有用)
4
script_this at yahoo dot com
21年前
回复uthayakutty76 at yahoo dot com的
2003年6月30日12:31帖子

-----------------------------------------------------------
...问题是与MySQL
服务器的连接非常快地中断,或者根本没有
连接。我们发现,当使用
服务器的域名而不是“localhost”时,问题
会发生.....
-----------------------------------------------------------

尝试在my.cnf中为mysql设置wait_timeout变量为
非常高的值,这样连接就不会空闲那么长时间。
实际上很荒谬,但它适用于
本地主机或远程数据库服务器,而
本地主机解决方案我认为只有在数据库是本地时才有效。
i
4
mightye (at) mightye (dot) org
20年前
通常情况下,你**不**应该使用 `mysql_pconnect`。此函数的设计目标是针对连接数据库开销非常大的环境。在典型的 MySQL/Apache/PHP 环境中,Apache 会创建许多子进程,这些子进程处于空闲状态,等待分配 Web 请求。每个子进程都会打开并保持其自身的 MySQL 连接。因此,如果你的 MySQL 服务器连接数限制为 50,但 Apache 保持运行的子进程超过 50 个,则即使这些子进程处于空闲状态(空闲的 httpd 子进程不会将其 MySQL 连接借给其他 httpd 子进程,它们拥有自己的连接),每个子进程也都会占用你的 MySQL 服务器的一个连接。所以,即使在一个繁忙的站点上只有少数页面实际连接到 MySQL,你仍然可能会耗尽连接,而所有这些连接实际上都没有被使用。

一般情况下,除非建立连接需要很长时间,否则请使用 `mysql_connect()` 连接到 MySQL。
3
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 中的脚注)
2
matt *at* roughest *dot* net
20年前
在运行多个 MySQL 服务器的机器上使用持久连接时,务必小心。必须指定正确的套接字路径,否则 PHP 将重用连接,而不管它们连接到哪个服务器。也就是说,它会看到具有匹配参数的打开连接并使用它,即使该连接实际上是针对不同的服务器。
2
spam at vrana dot cz
21年前
警告:如果在服务器上不同的脚本中对 `mysql_pconnect()` 使用不同的参数,PHP 可能会为每个进程中每组参数创建一个持久连接,最多为 `mysql.max_persistent`(PHP 指令)个。因此,即使你的 Apache 的 `MaxClients` 指令设置小于 MySQL 的 `max_connections` 指令,你也很容易出现 MySQL 的“Too many connections”错误。

如果 `mysql.max_persistent` 设置为 -1(无限,默认值)以外的值,则超过此限制的连接将被静默拒绝,因此请谨慎使用。

解决方案:对于可能具有无限连接参数集的服务器,请使用 `mysql.allow_persistent=Off` 禁止持久连接。
1
3ch0
18年前
当你在大型网站上使用远程数据库服务器时,建议使用 `pconnect`。MySQL 特别是在保持 1 个打开的连接而不是每分钟 1000 个连接时会更稳定 =)
1
pulstar at mail dot com
21年前
当我使用 `mysql_pconnect` 并使用 `MYSQL_CLIENT_COMPRESS` 标志连接到远程服务器时遇到了一些问题。有时它可以连接,但很多时候它会给我以下错误:
警告:`mysql_pconnect(): Unknown database 'XXXXX'`

如果你遇到同样的问题,请尝试使用 `mysql_connect`。它对我很有效。脚本每次页面重新加载时都需要很长时间重新连接,但它将以压缩方式传输数据。这比通过互联网发送纯数据更安全,并且在传输大量数据时也更快。
2
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(
'Could not select database: ' . mysql_error());
continue;
}
$cons[] = $con;
}
}
// 如果没有服务器响应,则抛出异常。
if (count($cons) == 0) {
throw new
Exception
('Unable to connect to any database servers - last error: ' . mysql_error());
}
// 从活动连接列表中随机选择一个连接。
$serverIdx = rand(0, count($cons)-1);
$con = $cons[$serverIdx];
// 返回连接。
return $con;
}
}
?>
0
m at louislivi dot com
5年前
SMProxy
基于 MySQL 协议和 Swoole 的 MySQL 数据库连接池。
https://github.com/louislivi/SMProxy
0
shane
13年前
新的 mysqlnd 库(取代旧的 libmysql)应该可以解决连接消失的问题。它会在尝试使用连接之前刷新连接(使用 `change_user` 或 `ping`)。(它还使用更少的内存,并且通常具有更好的性能。)我只在 mysqli 中尝试过它,但原生扩展也使用它。它适用于 PHP >= 5.3、MySQL >= 4.1。
0
JM
16年前
如果您遇到与 /var/mysql/mysql.sock 相关的错误消息,请尝试修改您的 php.ini 文件,将 mysql.default_socket 设置为 /tmp/mysql.sock。
0
[email protected]
20年前
在 MySQL 中使用持久连接和临时表时务必小心:在 MySQL 中,临时表仅对当前连接可见,但如果您使用持久连接,则这些临时表据称对共享同一持久连接的所有用户可见。这可能导致严重问题。建议在使用持久连接时使用完全随机的临时表名称以避免重大问题。
0
[email protected]
20年前
我想评论一下 qualcomm.com 的 dfischer 发布的帖子,该帖子建议在多个应用程序调用中跨越事务,以防有人大胆尝试。

我假设使用的表类型是支持事务的类型之一,例如 InnoDB 或 BerkeleyDB。

首先,有一个问题是这是否根本有效。为了有效,事务上下文必须通过 Web 服务器跨所有 php 代码调用得以保留。阅读 https://php.net/manual/en/features.persistent-connections.php 的描述,保持事务上下文充其量是一种巧合。有趣的是,发现这有时确实有效,并了解这种行为的影响。如果我碰巧获得了您的连接,而我的操作是取消,您的更新可能会丢失。

其次,如果这样的事情确实有效(偶尔或总是有效),则由于底层数据库管理的事务几乎是无限期的,因此会产生性能影响。一些长时间运行的事务可能会在短时间内消耗大量资源,并发冲突的可能性也会增加。如果 mysql_pconnect 的行为是在 php 处理结束时保持事务打开,那么最好在使用 mysql_pconnect 时不定义事务。而且,从未由代码关闭的事务(用户出去吃午饭并被公共汽车撞到)可能会长时间占用资源(可能直到康复之后)。

因此,即使这样的方案可以工作,也不是一个好主意。事务应该在用户请求处理结束时提交或回滚。这允许 DBMS 正确管理资源利用率并防止对好数据造成不良影响。如果 mysql_pconnect 与数据库引擎的事务组件不能很好地协调以始终在处理请求结束时结束事务,则不应在使用 begin transaction 的情况下使用 mysql_pconnect。
0
[email protected]
20年前
如果您有跨越多个页面的事务,您也可以考虑使用 pconnect。例如,在我的开发应用程序中,在我查询选择用户计划编辑的数据时启动事务。然后,在用户点击提交按钮并提交数据后,我提交事务。

我不能简单地使用 mysql_connect,因为连接将在页面结束时终止,如果我没有提交事务,它将自动回滚。
0
[email protected]
20年前
在 MySQL 运行在一台主机但多个端口(多数据库配置)的情况下,不要使用 pconnect。php 中的连接池算法显然只依赖于主机、用户名和密码,而不依赖于端口。因此,如果您使用相同的主机、用户名和密码,但端口不同,您可能会获得连接到与您请求的端口不同的端口的连接。
0
[email protected]
21年前
使用 mysql_pconnect 时要小心。如果您在 ISP 上托管,他们可能会反对您使用多个持久性 mysql 连接,因为这会更长时间地消耗资源。如果您的脚本崩溃,您的连接可能会长时间保持打开状态。如果涉及循环,您可能会意外地耗尽所有可用连接。ISP 可能会认为这是滥用行为,您可能会遇到麻烦。首先尝试使用 mysql_connect。90% 的时间,非持久性 mysql_connect 调用都能很好地完成任务。
0
[email protected]
22年前
使用持久连接时,您需要非常小心地使用 LOCK TABLES。如果脚本在执行 UNLOCK TABLES 之前终止,则表将保持锁定状态,并且很可能会挂起未来的脚本。这在错误报告中有所提及,但仍未反映在文档中:http://bugs.php.net/bug.php?id=7634
0
[email protected]
22年前
在 Linux 下运行 Apache 的 PHP 4.1.1 在处理持久性 mysql 连接时似乎没有执行所有必要的刷新操作。请自行尝试。在 pconnect 会话中创建一个临时表,添加行(非唯一),选择/显示并删除表。现在多次重新加载您的脚本,您会看到您的结果不一致,即使您每次都创建一个新表并删除它。

我遇到了 pconnect 的一些问题,建议您除非绝对必要,否则不要使用它。在这种情况下,请确保您测试结果的一致性,尤其是在您的查询涉及临时表或 mysql 会话变量时。

Bartek Bulzak
-1
David
15年前
在我升级到 PHP 5.3 之后,我开始在来自 apache 服务器的几乎每个其他页面请求上收到“MySQL 服务器已断开连接”错误。我尝试了一些不起作用的方法。以下是解决方案:我将所有 mysql_pconnect() 语句更改为 mysql_connect()。它解决了这个问题。由于某种原因,PHP 5.3 不喜欢持久连接。
-1
[email protected]
24年前
如果您需要关闭空闲的持久连接,请在 MySQL 中设置较低的 wait_timeout。
-1
Sabyasachi Ruj
17年前
如果您使用的是 mysql_pconnect(),并且假设 MySQL 服务器为该客户端池化了五个持久连接。

现在 mysql_pconnect 可以返回其中的任何一个。

因此,如果您期望 mysql_pconnect 总是使用相同的持久连接,事实并非如此。

因此,假设您在使用 mysql_pconnect 连接后执行

set @aa=6;

在另一个页面中,您再次使用了 mysql_pconnect,并执行了

select @aa;

这不会必然返回 '6' 作为结果!

因为第二个 mysql_pconnect 可以从该服务器的连接池中获取另一个持久连接。
-1
[email protected]
21年前
您可以通过在 php 配置文件中设置指令 mysql.allow_persistent = Off 来解决持久连接问题。尝试创建持久连接 /mysql_pconnect()/ 的用户将连接到数据库
使用非持久连接 /mysql_connect()/

有关更多信息,请参阅持久连接部分的用户说明。https://php.net/manual/en/features.persistent-connections.php
--
http://www.id.com.ua Ilya Rudenko
-2
Nils Meyer [email protected]
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(),如前所述,它在大多数环境中更有意义,而且不需要处理那么多事情(例如变量、事务、临时表)。
-2
[email protected]
19年前
您可以设置 interactive_timeout 为较短的时间段(例如 20 秒),而不是使用 wait_timeout,这在 apache + mysql 环境中比 wait_timeout 好得多。

要了解有关 interactive_timeout 的更多信息,请参阅 mysql 文档。
-2
[email protected]
21年前
不要将事务(例如使用 InnoDB MySQL 表)与持久连接一起使用。如果您的脚本由于任何原因停止或退出,您的事务将保持打开状态,并且您的锁将保持锁定状态。您必须重置 MySQL 才能释放它们(据我所知)。它们不会像应该的那样在错误时自动回滚。当您重新启动脚本时,您将获得一个新的连接,因此您无法回滚或提交之前的脚本。任何具有 start transaction、rollback 或 commit SQL 语句的脚本都应该使用常规(而非持久性)连接。PHP 似乎应该在脚本退出(错误或其他)且没有 COMMIT 时自动发出针对任何打开事务的 ROLLBACK。Zend 的网站对此有一个简短的介绍。混合使用是可以的,因此您可以对读取内容使用持久连接,但根据条件(如果您必须更新,这通常不太频繁)打开新的常规连接。
-4
Tom
14年前
与上述建议(持久连接仅适用于模块版本)相反,持久连接非常适用于由 FastCGI 管理的 CGI PHP。这是因为 FastCGI 在请求之间保持 PHP 进程运行。在这种模式下,持久连接也很容易不受连接限制的影响,因为您可以设置 PHP_FCGI_CHILDREN << mysql 的 max_connections <<< Apache 的 MaxClients。这也能节省资源。
To Top