Управление подключением базы данных MySQL в PDO

Я очень новичок в PHP/MySQL, и я изучаю вещи, когда я иду. Одна из новых вещей, которые я узнал, заключается в том, что существует максимальное количество подключений к базе данных для данного имени пользователя. Когда я впервые начал создавать свой сайт в Wordpress, я использовал старые команды mysql_query(). Мне никогда не приходилось подключаться к базе данных MySQL, потому что Wordpress поддерживает активное соединение, только будучи зарегистрированным на веб-сайте. Когда я решил переключить все мои запросы MySQL на расширение PDO, я больше не мог использовать активное соединение Wordpress и должен был запускать свои собственные подключения к базе данных. Я сделал это в отдельном файле конфигурации PHP, который я включил в каждую страницу с script. Код 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 в конце каждого script (хотя это должно быть PHP PDO по умолчанию?). Затем я попытался установить каждый дескриптор инструкции null после каждого запроса базы данных (это было безнадежным делом). И, наконец, я попытался использовать постоянное соединение, изменив следующую строку в моем файле конфигурации:

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

Ничто из этого не работает, и я все равно получаю ту же самую точную ошибку. Сайт, когда он готов, должен иметь возможность обрабатывать 100-200 человек в день, вводя множество разных данных. Даже если я смогу понять, как использовать активное соединение Wordpress с использованием PDO, это было бы хорошим началом. Буду признателен за любую помощь, которую я могу получить.

UPDATE:

Я запускаю SHOW FULL PROCESSLIST как запрос MySQL в одном из моих кодов, и я получаю очень странное поведение. Это первая часть моего script (не включая запрос 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();
}
} ?>

Если я попытаюсь запустить запрос SHOW PROCESS LIST за пределами оператора if, я получаю результат, заявляющий, что у меня есть одно активное соединение; однако, если я попытаюсь запустить запрос SHOW FULL PROCESSLIST внутри оператора if, я получаю ошибку, которую превысил количество подключений. Исходя из этого результата, я предположил, что, возможно, моя строка include на самой верхней части страницы может вызвать проблему, когда пользователь отправляет свою форму (по существу, пытается дважды подключиться к базе данных), поэтому я переместил ее внутри оператора if, но это тоже не имело никакого значения. Я не понимаю, почему это происходит.

UPDATE/ANSWER (еще некоторые вопросы):

Я понял, в чем моя проблема. По завершении одного из моих сценариев есть команда javascript, чтобы вывести окно, в котором другой script распечатает счет-фактуру для них. Эта вторая script также пытается установить соединение с базой данных с помощью файла конфигурации. Форма, с которой работает пользователь, является динамической (они могут помещать как можно меньше или столько наборов данных, сколько пожелают), поэтому, когда пользователь вставляет небольшое количество данных, запросы PDO выполняются очень быстро, и нет конфликта между количество соединений; однако, если пользователь вводит много данных, тогда требуется значительное количество времени, и максимальное количество соединений достигается сервером. Проблема действительно заключается в сочетании плохой серверной среды и неэффективных запросов с моей стороны (все еще изучая PHP). Единственное решение, о котором я могу думать в этот момент, - поставить более длинный сон на мой второй script (уже используя 3-секундный сон), чтобы другой script догнал, но в какой-то момент это будет просто слишком долго. Я не уверен, есть ли у вас лучшие предложения?

Ответ 1

Если у вас есть другой инструмент, который может дать вам соединение с базой данных, вы можете увидеть, сколько соединений вы на самом деле делаете. В крайнем случае phpmyadmin может это сделать.

Обычно вы можете видеть все ваши активные запросы и соединения с помощью:

SHOW PROCESSLIST

Если вы допустили ошибку в своей процедуре подключения к PDO, вы можете установить соединение для каждого запроса, который вы пытаетесь запустить, а не на протяжении всего запроса. Вам также может потребоваться проверить, что каждый запрос не создает большой пул соединений для вас, которые не закрыты должным образом. Вероятно, вам нужно поэкспериментировать с параметрами подключения.

Ответ 2

Использование include_once('config.php') или require_once('config.php') в файлах вместо include 'config.php' может быть вашим решением, чтобы избежать дублирования подключений к базе данных.

Ответ 3

То, что вам нужно, называется классом PDO "singleton". Вот пример:

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

Это не лучший пример, потому что конструктор принимает слишком много аргументов. Просто скопируйте $dsn,.., args в конструктор, т.е. _construct() {...}, и вы можете использовать новый sdb(), где бы вы не использовали PDO(). Нет необходимости в каких-либо приложениях include или require, за исключением одного раза для класса.

Объект $pdo хранится как статическая переменная внутри класса и поэтому всегда доступен.