简体   繁体   English

PDO中的MySQL数据库连接管理

[英]MySQL Database Connection Management In PDO

I'm very new to PHP/MySQL and I'm learning things as I go. 我是PHP / MySQL的新手,我正在学习的东西。 One of the newer things I've learned is that there is a maximum number of connections that can be made to a database for a given username. 我学到的一个新事物是,对于给定的用户名,可以为数据库建立最大数量的连接。 When I first started building my website on Wordpress, I was using the old mysql_query() commands. 当我第一次开始在Wordpress上构建我的网站时,我使用的是旧的mysql_query()命令。 I never had to make a connection to the MySQL database because Wordpress keeps an active connection just by being logged in on the website. 我从来没有必要连接到MySQL数据库,因为Wordpress只是通过登录网站保持活动连接。 When I decided to switch all my MySQL queries over to the PDO extension, I could no longer take advantage of Wordpress' active connection, and had to start my own database connections. 当我决定将所有MySQL查询切换到PDO扩展时,我再也无法利用Wordpress的活动连接,并且必须启动自己的数据库连接。 I did this in a separate PHP config file that I included in every page that ran a script. 我在一个单独的PHP配置文件中执行了此操作,该文件包含在运行脚本的每个页面中。 The PHP code looks like this: PHP代码如下所示:

try {
    $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
}
catch(PDOException $e) {  
    echo "Select DB Error: " .$e->getMessage(). "</br>";
}

Unfortunately now, I constantly get the following error: 不幸的是,我经常遇到以下错误:

" SQLSTATE[42000] [1203] User already has more than 'max_user_connections' active connections" “SQLSTATE [42000] [1203]用户已超过'max_user_connections'活动连接”

Based on some online research, I tried various different methods to fix this. 基于一些在线研究,我尝试了各种不同的方法来解决这个问题。 First, I tried to set the database connection to null at the end of each script (though this should be PHP PDO's default?). 首先,我尝试在每个脚本的末尾将数据库连接设置为null(尽管这应该是PHP PDO的默认值?)。 Then I tried to set each statement handle to null after each query of the database (this was a hopeless endeavor). 然后我尝试在每次数据库查询后将每个语句句柄设置为null (这是一种无望的努力)。 And finally, I tried using a persistent connection by changing the following line in my config file: 最后,我尝试通过更改配置文件中的以下行来使用持久连接:

$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass, array(PDO::ATTR_PERSISTENT => true));

None of this seems to work and I still get the same exact error. 这似乎都不起作用,我仍然得到同样的错误。 The site, when ready, needs to be able to handle 100-200 people per day entering a myriad of different data. 该网站准备好后,每天需要能够处理100-200人,输入大量不同的数据。 Even if I can figure out how to take advantage of Wordpress' active connection using PDO, that would be a good start. 即使我可以弄清楚如何利用Wordpress的PDO主动连接,这将是一个良好的开端。 I'd appreciate any help I can get. 我很感激我能得到任何帮助。

UPDATE: 更新:

I'm running SHOW FULL PROCESSLIST as a MySQL query in one of my codes and I'm getting very strange behavior. 我在我的一个代码中运行SHOW FULL PROCESSLIST作为MySQL查询,我的行为非常奇怪。 This is the first part of my script (not including the SHOW FULL PROCESSLIST query): 这是我脚本的第一部分(不包括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 I try to run the SHOW PROCESS LIST query outside of the if statement, I get a result stating that I have one active connection; 如果我尝试在if语句之外运行SHOW PROCESS LIST查询,我会得到一个结果,表明我有一个活动连接; however, if I try to run the SHOW FULL PROCESSLIST query inside the if statement, I get the error that I have exceeded my number of connections. 但是,如果我尝试运行SHOW FULL PROCESSLIST if语句的查询,我得到的,我已经超过了我的连接数的错误。 Based on this result, I figured perhaps my include line on the very top of the page may be causing an issue when the user submits their form (essentially trying to connect to the database twice), so I moved it inside the if statement, but that made no difference either. 根据这个结果,我想,当用户提交表单(主要是尝试连接数据库两次)时,页面顶部的include行可能会引起问题,所以我把它移到了if语句中,但是也没有任何区别。 I'm at a loss as to why this happening. 我不知道为什么会发生这种情况。

UPDATE/ANSWER (still some questions): 更新/答案(仍有一些问题):

I figured out what my issue was. 我弄清楚我的问题是什么。 Upon completion of one of my scripts, there is a javascript command to pop up a window where another script will print out an invoice for them. 完成我的一个脚本后,有一个javascript命令可以弹出一个窗口,其中另一个脚本会为它们打印出发票。 That second script also tries to make a connection to the database using the config file. 第二个脚本还尝试使用配置文件建立与数据库的连接。 The form the user is working with is dynamic (they can put in as little or as many data sets as they wish), so when the user inserts a small number of data, the PDO queries are performed very fast and there is no conflict between the number of connections; 用户使用的表单是动态的(他们可以根据需要输入尽可能少的数据集),因此当用户插入少量数据时,PDO查询执行速度非常快,并且之间没有冲突连接数量; however, if the user inputs a lot of data then it takes a significant more amount of time, and the maximum number of connections is reached by the server. 但是,如果用户输入大量数据,则需要花费更多的时间,并且服务器可以达到最大连接数。 The issue really resides in a combination of poor server environment and inefficient queries on my part (still learning PHP). 这个问题确实存在于糟糕的服务器环境和低效查询的组合中(仍在学习PHP)。 The only solution I can think of at this point is to put a longer sleep on my second script (already using a 3 second sleep), to let the other script catch up, but at some point, this will just take too long. 我现在能想到的唯一解决方案是在我的第二个脚本(已经使用3秒睡眠)上进行更长时间的睡眠,让另一个脚本赶上,但在某些时候,这将花费太长时间。 I'm not sure if you guys have any better suggestions? 我不确定你们有没有更好的建议?

If you have another tool that can give you a connection to the database you might want to see how many connections you're actually making. 如果您有另一个可以为您提供与数据库连接的工具,您可能希望查看实际建立的连接数。 In a pinch, phpmyadmin can do this. 在紧要关头, phpmyadmin可以做到这一点。

Usually you can see all your active queries and connections with: 通常,您可以看到所有活动查询和连接:

SHOW PROCESSLIST

If you have made a mistake in your PDO connection routine you may be making a connection for each query you're trying to run rather than one for the duration of the request. 如果您在PDO连接例程中犯了错误,则可能正在为您尝试运行的每个查询建立连接,而不是在请求期间连接。 You may also need to check that each request is not creating a large pool of connections for you that aren't closed properly. 您可能还需要检查每个请求是否未为您创建未正确关闭的大型连接池。 You probably need to experiment with connection options. 您可能需要尝试连接选项。

在文件中使用include_once('config.php')require_once('config.php')而不是include 'config.php'可能是避免重复数据库连接的解决方案。

What you need is called a PDO "singleton" class. 你需要什么被称为PDO“单身”类。 Here is an example: 这是一个例子:

http://tonylandis.com/php/php5-pdo-singleton-class/ http://tonylandis.com/php/php5-pdo-singleton-class/

It is not the best example because the constructor takes too many arguments. 它不是最好的例子,因为构造函数需要太多参数。 Just hardcode the $dsn,.., args into the constructor ie. 只需将$ dsn,..,args硬编码到构造函数中即。 _construct(){...} and you can use new sdb() wherever you would have used PDO(). _construct(){...}并且您可以在任何使用PDO()的地方使用新的sdb()。 No need for any include or require statements except once for the class. 除了一次课外,不需要任何包含或要求声明。

The $pdo object is stored as a static variable inside the class and so is always accessible. $ pdo对象作为静态变量存储在类中,因此始终可以访问。

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

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