我是PHP / MySQL的新手,我正在学习的东西。我学到的一个新事物是,对于给定的用户名,可以为数据库建立最大数量的连接。当我第一次开始在Wordpress上构建我的网站时,我使用的是旧的mysql_query()命令。我从来没有必要连接到MySQL数据库,因为Wordpress只是通过登录网站保持活动连接。当我决定将所有MySQL查询切换到PDO扩展时,我再也无法利用Wordpress的活动连接,并且必须启动自己的数据库连接。我在一个单独的PHP配置文件中执行了此操作,该文件包含在运行脚本的每个页面中。 PHP代码如下所示:
try {
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
}
catch(PDOException $e) {
echo "Select DB Error: " .$e->getMessage(). "</br>";
}
不幸的是,现在,我经常遇到以下错误:
“SQLSTATE [42000] [1203]用户已超过'max_user_connections'活动连接”
基于一些在线研究,我尝试了各种不同的方法来解决这个问题。首先,我尝试在每个脚本的末尾将数据库连接设置为null(尽管这应该是PHP PDO的默认值?)。然后我尝试在每次查询数据库之后将每个语句句柄设置为null
(这是一种无望的努力)。最后,我尝试通过更改配置文件中的以下行来使用持久连接:
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass, array(PDO::ATTR_PERSISTENT => true));
这些似乎都不起作用,我仍然得到同样的错误。该网站准备好后,每天需要能够处理100-200人,输入大量不同的数据。即使我可以弄清楚如何利用Wordpress的PDO主动连接,这将是一个良好的开端。我很感激能得到的任何帮助。
更新:
我在我的一个代码中运行SHOW FULL PROCESSLIST
作为MySQL查询,我的行为非常奇怪。这是我脚本的第一部分(不包括SHOW FULL PROCESSLIST
查询):
<?php
include 'config.php';
if(isset($_POST['submit']))
{
//Get Current User Login
global $current_user;
$current_user = wp_get_current_user();
$ulog = $current_user->user_login;
$tablename_cc = "cc_".$ulog;
$tablename_db = "db_".$ulog;
$tablename_misc = "misc_".$ulog;
$tablename_cash = "cash_".$ulog;
try {
$DBH->exec("CREATE TABLE IF NOT EXISTS " .$tablename_cc. " (ID bigint(100) NOT NULL AUTO_INCREMENT, PRIMARY KEY(ID), accnt TEXT(20), cc_num TEXT(4), cc_amnt DECIMAL(8,2), cc_app TEXT(20), cc_date VARCHAR(10), cc_time VARCHAR(10))");
$DBH->exec("CREATE TABLE IF NOT EXISTS " .$tablename_db. " (ID bigint(100) NOT NULL AUTO_INCREMENT, PRIMARY KEY(ID), accnt TEXT(20), db_num TEXT(20), db_amnt DECIMAL(8,2), db_date VARCHAR(10), db_time VARCHAR(10))");
$DBH->exec("CREATE TABLE IF NOT EXISTS " .$tablename_misc. " (ID bigint(100) NOT NULL AUTO_INCREMENT, PRIMARY KEY(ID), accnt TEXT(20), misc_item TEXT(1000), misc_amnt DECIMAL(8,2), misc_date VARCHAR(10), misc_time VARCHAR(10))");
$DBH->exec("CREATE TABLE IF NOT EXISTS " .$tablename_cash. " (ID bigint(100) NOT NULL AUTO_INCREMENT, PRIMARY KEY(ID), accnt TEXT(20), cash_amnt DECIMAL(8,2), cash_time VARCHAR(10))");
}
catch(PDOException $e) {
echo "Create Tables Error: " .$e->getMessage();
}
} ?>
如果我尝试在if语句之外运行SHOW PROCESS LIST
查询,我会得到一个结果,表明我有一个活动连接;但是,如果我尝试在 if语句中运行SHOW FULL PROCESSLIST
查询,我会收到超出连接数的错误。基于这个结果,我想可能在页面顶部的include
行可能导致用户提交表单时出现问题(基本上是尝试连接数据库两次),所以我把它移到了如果声明,但这也没有任何区别。我不知道为什么会发生这种情况。
更新/答案(仍有一些问题):
我弄清楚我的问题是什么。完成我的一个脚本后,有一个javascript命令可以弹出一个窗口,其中另一个脚本会为它们打印出发票。第二个脚本还尝试使用配置文件建立与数据库的连接。用户使用的表单是动态的(他们可以根据需要输入尽可能少的数据集),因此当用户插入少量数据时,PDO查询执行速度非常快,并且之间没有冲突连接数量;但是,如果用户输入大量数据,则需要花费更多的时间,并且服务器可以达到最大连接数。这个问题确实存在于糟糕的服务器环境和低效查询的组合中(仍在学习PHP)。我现在能想到的唯一解决方案是在我的第二个脚本(已经使用3秒睡眠)上进行更长时间的睡眠,让另一个脚本赶上,但在某些时候,这将花费太长时间。我不确定你们有没有更好的建议?
答案 0 :(得分:2)
如果您有其他工具可以为您提供与数据库的连接,您可能希望查看实际建立的连接数。在紧要关头,phpmyadmin
可以做到这一点。
通常,您可以看到所有活动查询和连接:
SHOW PROCESSLIST
如果您在PDO连接例程中犯了错误,则可能正在为您尝试运行的每个查询建立连接,而不是在请求期间连接。您可能还需要检查每个请求是否未为您创建未正确关闭的大型连接池。您可能需要尝试连接选项。
答案 1 :(得分:1)
在文件而不是include_once('config.php')
中使用require_once('config.php')
或include 'config.php'
可能是避免重复数据库连接的解决方案。
答案 2 :(得分:0)
您需要的是一个PDO“单身”类。这是一个例子:
http://tonylandis.com/php/php5-pdo-singleton-class/
这不是最好的例子,因为构造函数需要太多参数。只需将$ dsn,..,args硬编码到构造函数中即。 _construct(){...}并且您可以在任何使用PDO()的地方使用新的sdb()。除了上课之外,不需要任何包含或要求声明。
$ pdo对象作为静态变量存储在类中,因此始终可以访问。