Qu'est-ce qui provoque une erreur PDO Impossible d'exécuter des requêtes alors que d'autres requêtes sans tampon sont actives?
J'ai le code suivant:
$dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $dbh->prepare("SELECT 1");
$stmt->execute();
$result = $stmt->fetch();
$stmt->execute();
$result = $stmt->fetch();
$stmt = $dbh->prepare("SELECT 1");
$stmt->execute();
$result = $stmt->fetch();
Cependant, pour certaines raisons, j'obtiens l'erreur suivante lors de l'exécution de la deuxième déclaration préparée à l'avance:
Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[HY000]: General error: 2014 Ne peut pas exécuter des requêtes tout en
d'autres barrettes de mémoire les requêtes sont actifs. Pensez à utiliser
PDOStatement::fetchAll(). Alternativement, si votre code n'est jamais
va à l'encontre de mysql, vous pouvez permettre à une requête de mise en mémoire tampon par la mise en
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribut.'
Je sais ce que cette erreur signifie et comment résoudre le problème (de le faire) unset($stmt);
ou $stmt->closeCursor();
), donc je ne suis pas à la recherche d'une solution de comment le faire fonctionner. À partir de ce que je comprends, elle est généralement causée par faire fetch
au lieu de fetchAll
et de ne pas récupérer tous les résultats. Toutefois, dans ce cas, il y a un seul résultat et elle est récupérée. Aussi, si je n'exécuter la première instruction préparée une fois, l'erreur ne se produit pas. Il ne se produit que lors de la première exécution de l'instruction deux fois. De plus, cela ne se produit lorsque PDO::ATTR_EMULATE_PREPARES
est false
.
Donc ma question est, quelle est la cause de l'erreur ci-dessus à se produire dans ce cas? Il ne semble pas être différente de toute autre requête que j'ai jamais exécutée.
J'ai testé sur deux Ubuntu 13.10 serveurs, Debian et CentOS et produisent tous le même message d'erreur à l'aide de la valeur par défaut des paquets.
Edit:
Pour répondre à Ryan Vincent commentaire, je suis un complet mysqli noob, mais je crois que ce que j'ai ci-dessous est à peu près équivalent à l'exemple ci-dessus. S'il vous plaît corrigez-moi si je me trompe. Cependant, il ne produit pas d'erreurs, de sorte qu'il semble être un AOP seule erreur:
$mysqli = new mysqli($host, $user, $pass, $dbname);
if ($mysqli->connect_errno) {
die("Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error);
}
if (!($stmt = $mysqli->prepare("SELECT 1"))) {
die("Prepare 1 failed: (" . $mysqli->errno . ") " . $mysqli->error);
}
if (!$stmt->execute()) {
die("Execute 1 failed: (" . $stmt->errno . ") " . $stmt->error);
}
$stmt->store_result();
$stmt->bind_result($col1);
$stmt->fetch();
if (!$stmt->execute()) {
die("Execute 2 failed: (" . $stmt->errno . ") " . $stmt->error);
}
$stmt->store_result();
$stmt->bind_result($col1);
$stmt->fetch();
if (!($stmt = $mysqli->prepare("SELECT 1"))) {
//The following line is what fails in PDO
die("Prepare 2 failed: (" . $mysqli->errno . ") " . $mysqli->error);
}
if (!$stmt->execute()) {
die("Execute 3 failed: (" . $stmt->errno . ") " . $stmt->error);
}
$stmt->store_result();
$stmt->bind_result($col1);
$stmt->fetch();
source d'informationauteur Mike
Vous devez vous connecter pour publier un commentaire.
Curieusement, le PHP paquets fournis par Ubuntu ne sont pas compilés avec le le pilote natif Mysqlmais avec l'ancien libmysqlclient à la place (testé sur Ubuntu 13.10 avec les packages par défaut):
Votre cas de test ("Edit 4", avec
setAttribute(MYSQL_ATTR_USE_BUFFERED_QUERY, true)
) fonctionne comme prévu avec PHP 5.5.3 manuellement compilé avec mysqlnd avec:... mais échoue avec:
Il tout à fait étrange qu'il n'échoue que si la première instruction est exécutée deux fois; ce doit être un bug dans le libmysqlclient pilote.
Les deux pilotes ne comme prévu lors de la
MYSQL_ATTR_USE_BUFFERED_QUERY
estfalse
. Votre bon Sens l'a déjà démontré pourquoi ce comportement est normal, quel que soit le nombre de lignes dans le jeu de résultats.Mike a trouvé que la solution actuelle est d'installer le
php5-mysqlnd
paquet au lieu de la forme Canonique-recommandéphp5-mysql
.Il semble que vous avez
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
définie sur FALSE.Et dans ce cas, il est obligatoire pour s'assurer qu'il n'y a plus de lignes dans l'attente de la récupération. Pour ce faire un pour courir
fetch()
une fois de plus, comme il semble quefetch()
retour de faux est de "libérer" les non-buffered resultset en quelque sorte. Sans un tel appel supplémentaire non tamponnée resultset reste verrouillé et provoquant des "Commandes de synchronisation" erreurCe n'est pas nécessairement la réponse à cette question, mais cela peut aider quelqu'un dans le futur.
Je suis tombé sur exactement le même message d'erreur et il a fallu des heures pour découvrir ce qui n'allait pas. Il s'est avéré que c'était juste un fait mineur syntaxe question tout au long de. Si vous n'êtes pas vraiment à l'aide de toute mise en mémoire tampon, mais toujours cette erreur, comme je l'ai fait, ce pourrait être votre problème - afin de vérifier votre code.
Je faisais mes normale requêtes de base de données lorsque je suis tombé sur cette erreur -- pas volontairement à l'aide de toutes les techniques de mise en mémoire tampon -- donc, je doutais fortement qu'il n'avait rien à voir avec mise en mémoire tampon. J'ai lu TELLEMENT de question à ce sujet et regarda de plus profond en elle.
C'était mon STUPIDE syntaxe question:
Ce fait que je l'obtention de cette mise en mémoire tampon d'erreur. J'ai corrigé le code, et il s'en alla. Ce qui était le plus gênant, était le fait que l'AOP erreur a été pointant une autre requête, la requête suivante, mais cette requête a été dans une fonction ailleurs dans le code, et que, grâce à moi, bien sûr!
Juste pour compléter la liste des erreurs possibles à l'origine de ce problème ... parce que je perdais mes cheveux, je veux partager ma solution/trouver avec vous.
Dans mon cas, j'ai essayé d'envoyé plusieurs états à la base de données avec PDO::exec
par exemple
1 seule Instruction SQL dans 1 PDO::exec est permis et enregistrer.