简体   繁体   English

如果打开的连接太多,如何获得 php pdo 代码以继续重试连接?

[英]How can I get php pdo code to keep retrying to connect if there are too many open connections?

I have an issue, it has only cropped up now.我有一个问题,它现在才出现。 I am on a shared web hosting plan that has a maximum of 10 concurrent database connections.我使用的是共享 web 托管计划,该计划最多有 10 个并发数据库连接。 The web app has dozens of queries, some pdo, some mysql_*. web app有几十个查询,有的是pdo,有的是mysql_*。

Loading one page in particular peaks at 5-6 concurrent connections meaning it takes a minimum of 2 users loading it at the same time to spit an error on one or both of them.加载一个页面特别是在 5-6 个并发连接时达到峰值,这意味着至少需要 2 个用户同时加载它才能在其中一个或两个上吐出错误。

I know this is inefficient, I'm sure I can cut that down quite a bit, but that's what my idea is at the moment is to move the pdo code into a function and just pass in a query string and an array of variables, then have it return an array (partly to tidy my code).我知道这是低效的,我相信我可以减少很多,但这就是我目前的想法是将 pdo 代码移动到 function 中,然后只传递一个查询字符串和一个变量数组,然后让它返回一个数组(部分是为了整理我的代码)。

THE ACTUAL QUESTION:实际问题:

How can I get this function to continue to retry until it manages to execute, and hold up the script that called it (and any script that might have called that one) until it manages to execute and return it's data?我怎样才能让这个 function 继续重试直到它设法执行,并阻止调用它的脚本(以及任何可能调用该脚本的脚本)直到它设法执行并返回它的数据? I don't want things executing out of order, I am happy with code being delayed for a second or so during peak times我不希望事情乱序执行,我很高兴代码在高峰时段延迟一秒左右

Since someone will ask for code, here's what I do at the moment.由于有人会要求代码,这就是我目前所做的。 I have this in a file on it's own so I have a central place to change connection parameters.我把它放在一个单独的文件中,所以我有一个中心位置来更改连接参数。 the if statement is merely to remove the need to continuously change the parameters when I switch from my test server to the liver server当我从测试服务器切换到肝脏服务器时,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";

I 'include' that file at the top of a function我将该文件“包含”在 function 的顶部

 include 'db_connection_params.php';
        $pdo_conn = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);

then run commands like this all on the one connection然后在一个连接上运行这样的命令

$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
}

You shouldn't need 5-6 concurrent connections for a single page, each page should only really ever use 1 connection. 对于单个页面,您不需要5-6个并发连接,每个页面应该只使用1个连接。 I'd try to re-architect whatever part of your application is causing multiple connections on a single page. 我会尝试重新构建应用程序的任何部分,导致单个页面上出现多个连接。

However, you should be able to catch a PDOException when the connection fails ( documentation on connection management ), and then retry some number of times. 但是,您应该能够在连接失败时捕获PDOException( 连接管理文档 ),然后重试多次。

A quick example, 一个简单的例子,

<?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 concurrent connections is A LOT. 10个并发连接很多。 It can serve 10-15 online users easily. 它可以轻松地为10-15名在线用户服务。 Heavy efforts needed to exhaust them. 需要付出沉重的努力来消耗它们
So there is something wrong with your code. 所以你的代码有问题。

There are 2 main reasons for it: 主要原因有两个:

  • slow queries take too much time and thus serving one hit uses one mysql connection for too long. 慢查询花费太多时间,因此服务一次命中使用一个mysql连接太长时间。
  • multiple connections opened from every script. 从每个脚本打开多个连接。

The former one have to be investigated but for the latter one it's simple: 前一个必须进行调查,但对于后者,它很简单:

  1. Do not mix myqsl_ and PDO in one script: you are opening 2 connections at a time. 不要在一个脚本中混用myqsl_和PDO:您一次打开2个连接。
  2. When using PDO, open connection only once and then use it throughout your code. 使用PDO时,只打开一次连接,然后在整个代码中使用它。

Reducing the number of connections in one script is the only way to go. 减少一个脚本中的连接数是唯一的方法。
If you have multiple instances of PDO class in your code, you will need to add that timeout handling code you want to every call. 如果代码中有多个PDO类实例,则需要在每次调用时添加所需的超时处理代码。 So, heavy code rewriting required anyway. 因此,无论如何都需要重编码重写。
Replace these new instances with global $pdo; global $pdo;替换这些新实例global $pdo; instead. 代替。 It will take the same amount of time but it will be permanent solution, not temporary patch as you want it. 它将花费相同的时间,但它将是永久的解决方案,而不是您想要的临时补丁。
Please be sensible. 请明智。

PHP automatically closes all the connections st the end of the script, you don't have to care about closing them manually. PHP会自动关闭脚本末尾的所有连接,您不必关心手动关闭它们。
Having only one connection throughout one script is a common practice. 在一个脚本中只有一个连接是常见的做法。 It is used by ALL the developers around the world. 它被世界各地的所有开发人员使用。 You can use it without any doubts. 你可以毫无疑问地使用它。 Just use it. 只是使用它。

If you have transaction and want to log something in database you sometimes need 2 connections in one script如果你有事务并想在数据库中记录一些东西,你有时需要在一个脚本中有 2 个连接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM