De façon inattendue frapper PHP limite de mémoire avec une seule requête PDO?
J'ai une requête simple qui ressemble à quelque chose comme:
$result = $pdo->query('SELECT * FROM my_table');
foreach($result as $r) {
//do some stuff
}
Mais lorsque je l'exécute j'obtiens l'erreur suivante:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) in /path/to/myfile.php sur la ligne 15
"Ligne 15" étant le $pdo->query
ligne.
Si j'ai mis die()
après la requête, j'obtiens toujours la même erreur.
Je pensais que ce n'était plus censé chercher une ligne à la fois; pourquoi est-il l'aide d'autant de mémoire?
- Hrm? Comment est-ce pertinent? Je ne travaille qu'avec
$r
qui est un enregistrement unique. Pourquoi serait-ce la cause de récupérer des données supplémentaires? ...sauf si il y a une fuite de mémoire dans là et les itérations sont ce qui cause le problème...bien, je vais le poster. Pourquoi le downvote? - L'obtention de la mémoire réelle limite d'erreur serait également utile (le libellé utilisé, plesae), ce serait en fait vérification de l'utilisation de la mémoire immédiatement avant la requête. Vous avez peut-être déjà à la limite avant de la requête. Aussi, le nombre d'enregistrements retournés par la requête? Vous êtes en train de faire un
SELECT *
sansLIMIT
. Retour d'un million de lignes va utiliser juste un peu de mémoire. - Il n'y a rien avant la requête. Juste la connexion PDO. C'est un très petit script.
- Mec, c'est l'allocation de 32 octets et vous frappez un 128M limite? Vous avez vraiment besoin de vérifier l'utilisation de la mémoire avant de la requête. Aussi, quelle version de PHP est-ce?
- Voir la question des mises à jour.
- L'utilisation de la mémoire est 635384 octets avant d'appeler
query
. Je devinequery
alloue en morceaux, pour chaque enregistrement. Ne prouve pas beaucoup. C'est PHP 5.3.17. - bon, maintenant, le nombre de lignes renvoyées par la requête, composé de combien d'octets?
- Il y a ~350 K enregistrements dans la base de données. La PMA dit taille moyenne de ligne est de 159 octets.
- MySQL, droit? Êtes-vous à l'aide de
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
? C'est activé par défaut. - Bingo! Personnes handicapées, et maintenant, il fonctionne. Merci!!!! (Faire une réponse et je vais accepter)
Vous devez vous connecter pour publier un commentaire.
Ding ding ding!
Lors de la connexion à MySQL, PHP aime à l'aide de tampon de requêtes. Cela est vrai quelle que soit la méthode que vous utilisez pour vous connecter. Lors de l'utilisation de tampon de requêtes, l'ensemble du jeu de résultats est chargé immédiatement au lieu d'être récupérées lorsque vous demandez. C'est généralement bon pour les performances, car il y a moins d'aller-retours.
Mais comme tout en PHP, il y a une chasse aux sorcières. Comme indiqué sur la mise en mémoire tampon de page:
Vous êtes à l'aide de PHP 5.3, ce qui signifie qu'il ya une bonne chance que vous êtes à l'aide de mysqlnd.
Vous aurez envie de désactiver le tampon de requêtes ici. C'est fait différemment dans chaque interface PHP pour MySQL:
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
attributfalse
.MYSQLI_USE_RESULT
constante de larequête
méthode.mysql_unbuffered_query
au lieu demysql_query
.Plein de détails et d'exemples sur la page.
Gros tampon de requête gotcha!
Vous doit fermer correctement le descripteur d'instruction et gratuit le jeu avant la délivrance d'un autre requête:
closeCursor
sur le descripteur d'instruction.free_result
sur le descripteur d'instruction ougratuit
sur le résultat de la poignée, en fonction de ce que vous travaillez avec.mysql_free_result
Ne pas le faire entraînera une erreur.
closeCursor
si vous utilisezfetchAll
ou effectuer une itération sur l'ensemble de l'ensemble de résultats; seulement quand vous avez unfetched lignes à gauche. De toute façon, super réponse! Merci encore.