[英]How can I get php pdo code to keep retrying to connect if there are too many open connections?
我有一个问题,它现在才出现。 我使用的是共享 web 托管计划,该计划最多有 10 个并发数据库连接。 web app有几十个查询,有的是pdo,有的是mysql_*。
加载一个页面特别是在 5-6 个并发连接时达到峰值,这意味着至少需要 2 个用户同时加载它才能在其中一个或两个上吐出错误。
我知道这是低效的,我相信我可以减少很多,但这就是我目前的想法是将 pdo 代码移动到 function 中,然后只传递一个查询字符串和一个变量数组,然后让它返回一个数组(部分是为了整理我的代码)。
实际问题:
我怎样才能让这个 function 继续重试直到它设法执行,并阻止调用它的脚本(以及任何可能调用该脚本的脚本)直到它设法执行并返回它的数据? 我不希望事情乱序执行,我很高兴代码在高峰时段延迟一秒左右
由于有人会要求代码,这就是我目前所做的。 我把它放在一个单独的文件中,所以我有一个中心位置来更改连接参数。 当我从测试服务器切换到肝脏服务器时,if 语句只是为了消除不断更改参数的需要
$dbtype = "mysql";
$server_addr = $_SERVER['SERVER_ADDR'];
if ($server_addr == '192.168.1.10') {
$dbhost = "localhost";
} else {
$dbhost = "xxxxx.xxxxx.xxxxx.co.nz";
}
$dbname = "mydatabase";
$dbuser = "user";
$dbpass = "supersecretpassword";
我将该文件“包含”在 function 的顶部
include 'db_connection_params.php';
$pdo_conn = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
然后在一个连接上运行这样的命令
$sql = "select * from tbl_sub_cargo_cap where sub_model_sk = ?";
$capq = $pdo_conn->prepare($sql);
$capq->execute(array($sk_to_load));
while ($caprow = $capq->fetch(PDO::FETCH_ASSOC)) {
//stuff
}
对于单个页面,您不需要5-6个并发连接,每个页面应该只使用1个连接。 我会尝试重新构建应用程序的任何部分,导致单个页面上出现多个连接。
但是,您应该能够在连接失败时捕获PDOException( 连接管理文档 ),然后重试多次。
一个简单的例子,
<?php
$retries = 3;
while ($retries > 0)
{
try
{
$dbh = new PDO("mysql:host=localhost;dbname=blahblah", $user, $pass);
// Do query, etc.
$retries = 0;
}
catch (PDOException $e)
{
// Should probably check $e is a connection error, could be a query error!
echo "Something went wrong, retrying...";
$retries--;
usleep(500); // Wait 0.5s between retries.
}
}
10个并发连接很多。 它可以轻松地为10-15名在线用户服务。 需要付出沉重的努力来消耗它们
所以你的代码有问题。
主要原因有两个:
前一个必须进行调查,但对于后者,它很简单:
减少一个脚本中的连接数是唯一的方法。
如果代码中有多个PDO类实例,则需要在每次调用时添加所需的超时处理代码。 因此,无论如何都需要重编码重写。
用global $pdo;
替换这些新实例global $pdo;
代替。 它将花费相同的时间,但它将是永久的解决方案,而不是您想要的临时补丁。
请明智。
PHP会自动关闭脚本末尾的所有连接,您不必关心手动关闭它们。
在一个脚本中只有一个连接是常见的做法。 它被世界各地的所有开发人员使用。 你可以毫无疑问地使用它。 只是使用它。
如果你有事务并想在数据库中记录一些东西,你有时需要在一个脚本中有 2 个连接
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.