Мой сервер запускает CentOS 6.4 с MySQL 5.1.69, установленным с использованием yum с репозиториями CentOS, и PHP 5.4.16, установленным с помощью yum с ius repos. Редактировать3 Обновлено до версии сервера MySQL: 5.5.31 Распространяется проектом сообщества IUS, и ошибка все еще существует. Затем изменили библиотеку на mysqlnd и, похоже, устранили ошибку. Тем не менее, с этим взад и вперед, нужно знать, почему эта ошибка иногда проявляется.
При использовании PDO и создании объекта PDO с помощью PDO::ATTR_EMULATE_PREPARES=>false
я иногда получаю следующую ошибку:
Table Name - zipcodes
Error in query:
SELECT id FROM cities WHERE name=? AND states_id=?
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
File Name: /var/www/initial_install/build_database.php
Line: 547
Time of Error: Tuesday July 2, 2013, 5:52:48 PDT
Строка 547 - это последняя строка:
$stmt_check_county->execute(array($data[5],$data[4]));
if(!$county_id=$stmt_check_county->fetchColumn())
{
$stmt_counties->execute(array($data[5]));
$county_id=db::db()->lastInsertId();
}
//$stmt_check_county->closeCursor(); //This will fix the error
$stmt_check_city->execute(array($data[3],$data[4]));
У меня была аналогичная проблема несколько лет назад, но она обновилась с PHP 5.1 до PHP 5.3 (и MySQL, вероятно, также был обновлен), и проблема волшебным образом исчезла, и теперь у меня это с PHP 5.5.
Почему это проявляется только при PDO::ATTR_EMULATE_PREPARES=>false
и только с чередующейся версией PHP?
Я также обнаружил, что closeCursor()
также исправит ошибку. Должно ли это всегда выполняться после каждого запроса SELECT
, где fetchAll()
не используется? Обратите внимание, что ошибка все еще встречается, даже если запрос похож на SELECT COUNT(col2)
, который возвращает только одно значение.
Изменить. Кстати, так я создаю свое соединение. Я только недавно добавил MYSQL_ATTR_USE_BUFFERED_QUERY=>true
, однако он не излечивает ошибку. Кроме того, можно использовать следующий script как для создания ошибки.
function sql_error($e,$sql=NULL){return('<h1>Error in query:</h1><p>'.$sql.'</p><p>'.$e->getMessage().'</p><p>File Name: '.$e->getFile().' Line: '.$e->getLine().'</p>');}
class db {
private static $instance = NULL;
private function __construct() {} //Make private
private function __clone(){} //Make private
public static function db() //Get instance of DB
{
if (!self::$instance)
{
//try{self::$instance = new PDO("mysql:host=localhost;dbname=myDB;charset=utf8",'myUsername','myPassword',array(PDO::ATTR_EMULATE_PREPARES=>false,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC));}
try{self::$instance = new PDO("mysql:host=localhost;dbname=myDB;charset=utf8",'myUsername','myPassword',array(PDO::ATTR_EMULATE_PREPARES=>false,PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=>true,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC));}
//try{self::$instance = new PDO("mysql:host=localhost;dbname=myDB;charset=utf8",'myUsername','myPassword',array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC));}
catch(PDOException $e){echo(sql_error($e));}
}
return self::$instance;
}
}
$row=array(
'zipcodes_id'=>'55555',
'cities_id'=>123
);
$data=array($row,$row,$row,$row);
$sql = 'CREATE TEMPORARY TABLE temp1(temp_id INT UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY (temp_id) )';
db::db()->exec($sql);
$sql='SELECT COUNT(*) AS valid FROM cities_has_zipcodes WHERE cities_id=? AND zipcodes_id=?';
$stmt1 = db::db()->prepare($sql);
$sql ='SELECT temp_id FROM temp1';
$stmt2 = db::db()->prepare($sql);
foreach($data AS $row)
{
try
{
$stmt1->execute(array($row['zipcodes_id'],$row['cities_id']));
$rs1 = $stmt1->fetch(PDO::FETCH_ASSOC);
//$stmt1->closeCursor();
syslog(LOG_INFO,'$rs1: '.print_r($rs1,1).' '.rand());
$stmt2->execute();
$rs2 = $stmt2->fetch(PDO::FETCH_ASSOC);
syslog(LOG_INFO,'$rs2: '.print_r($rs2,1).' '.rand());
}
catch(PDOException $e){echo(sql_error($e));}
}
echo('done');