我的 Android 应用程序在使用基于 PHP/Mysql 的 Web 服务 API 时遇到问题。这是问题描述。
我在错误日志中收到以下错误。
User my-db-user already has more than 'max_user_connections' active connections
我的代码已耗尽 mysql 数据库连接
,并且我已达到主机可以提供的最大限制。我无法再增加 max_connections
和 max_user_connections
。
以下是我在 PHP 脚本中编写数据库访问代码的方法。我到处都遵循这种模式,所以在所有数据库访问类及其方法(如获取、插入、更新、删除等)中都是相同的。
DatabaseHelper.php
<?php
class DatabaseHelper {
private $db_host = 'my-host';
private $db_user = 'my-db-user';
private $db_password = 'my-password';
private $db_name = 'my-db-name';
public function getConnection() {
try {
$con = new mysqli($this->db_host, $this->db_user, $this->db_password, $this->db_name);
return $con;
} catch (Exception $ex) {
error_log('DB Error --> ' . $ex);
return null;
}
}
}
?>
这是我如何使用它的数据库访问类。
<?php
require_once (dirname(__FILE__) . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . "pathtofile" . DIRECTORY_SEPARATOR . 'DatabaseHelper.php');
class SomeDao {
public function get() {
$result = array();
$database = new DatabaseHelper();
$mysqli = $database->getConnection();
if ($mysqli != null) {
$stmt = $mysqli->stmt_init();
if ($stmt->prepare("SELECT columns FROM some_table")) {
$status = $stmt->execute();
if ($status) {
$stmt->bind_result($columns);
$records = array();
while ($stmt->fetch()) {
// build record array
$record = array();
// add key value pairs to array
$record["columns"] = $columns;
// add $record to $records
array_push($records, $record);
}
$result["statusCode"] = Constants::$OK;
$result["statusMessage"] = "OK";
$result["records"] = $records;
} else {
$result["statusCode"] = Constants::$SYSTEM_ERROR;
$result["statusMessage"] = "System Error." . $mysqli->error;
}
@$stmt->close();
} else {
$result["statusCode"] = Constants::$SYSTEM_ERROR;
$result["statusMessage"] = "System Error." . $mysqli->error;
}
@$mysqli->close();
} else {
$result["statusCode"] = Constants::$SYSTEM_ERROR;
$result["statusMessage"] = "System Error.";
}
return $result;
}
}
?>
我相信会有很多人像我一样遇到这个问题并成功解决。必须有某种方法来优化 mysql 数据库连接的使用,我想知道如何做到这一点。我只需要可以用来克服这个问题的最佳方法。
希望我已经清楚地说明了我的问题。请帮忙。
问候
最佳答案
为每个查询打开和关闭连接是非常浪费的。
这意味着每次将火柴棍移入和移出 table 时都要经历整个身份验证过程并创建不同的 TCP 连接。
您最终将得到一堆即将终止的 TCP 连接(存在 TCP 端口耗尽的风险),并使用相当大一部分带宽与数据库服务器交换密码。
此外,如果您碰巧忘记关闭其中一个连接,它可能会一直保持事件状态,直到脚本结束,从而减少可用连接的数量。可以说是一种“连接泄漏”。
典型的 session 应该如下所示:
open connection
do some stuff
do some stuff
do some stuff
do some stuff
close connection
而不是:
open / do stuff / close
open / do stuff / close
open / do stuff / close
open / do stuff / close
由于您已经有了一个帮助程序类,因此我建议您仅打开一次连接(当您实例化该帮助程序时),并在每次需要访问数据库时从中获取连接句柄。仅当助手被销毁时才应该关闭连接(即在最坏的情况下在脚本末尾,或者当助手超出范围时)。
另一个好处是,它将使您的代码更加紧凑。所有这些错误报告都比实际处理代码更庞大,这使得很难发现错误。最好在辅助对象中处理它们,以便代码可以专注于完成工作。
最后但并非最不重要的一点是,您可以在辅助对象中添加一致性检查。例如,计算静态类变量中打开的连接数,只是为了确保您没有无意中实例化更多的帮助程序或创建比您想象的更多的连接。
如果您遵循此模式,则每个当前事件的请求最多应有一个数据库连接,这将最大化您的响应能力。
如果您的页面始终通过 Ajax 执行六次查询,则达到限制的速度会快得多。尝试通过分解您的请求来减少数据库使用。
如果一些愚蠢的 SEO 机器人或精神病用户在您的网站上玩手提钻,除了监控客户端 IP 并拒绝那些执行过于频繁查询的人之外,您无能为力。
持久连接只会让您减轻一开始就做错事所造成的损害,因为“关闭”它们实际上不会这样做(并且重新打开它们也不会对它们产生任何影响),前提是您设置了正确的连接选项。
关于基于 PHP/Mysql 的 Web 服务 API,适用于没有 mysql 连接的移动应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20864926/