Introduction
Le driver natif MySQL gÚre la mémoire d'une façon différente que la bibliothÚque client MySQL. Les bibliothÚques diffÚrent dans la façon dont la mémoire est allouée et libérée, dans la façon dont la mémoire est allouée par morceau pendant la lecture des résultats depuis MySQL, quelles options de débogage et de développement existent, et comment les résultats lus depuis MySQL sont liés aux variables utilisateurs PHP.
Les notes suivantes sont une introduction et un résumé destinés aux utilisateurs intéressés par la compréhension du driver natif MySQL d'un point de vue du code C.
Fonctions utilisées dans la gestion mémoire
Toutes les allocations et les dĂ©-allocations sont rĂ©alisĂ©es en utilisant les fonctions de gestion de la mĂ©moire de PHP. Toutefois, la consommation mĂ©moire de mysqlnd peut ĂȘtre surveillĂ©e en utilisant des appels APIs PHP, comme memory_get_usage(). En raison du fait que la mĂ©moire est allouĂ©e et libĂ©rĂ©e en utilisant la gestion mĂ©moire de PHP, les modifications peuvent ne pas ĂȘtre immĂ©diatement visibles au niveau du systĂšme d'exploitation. Le gestionnaire de mĂ©moire PHP fonctionne comme un proxy qui peut avoir un peu de dĂ©lai dans la libĂ©ration mĂ©moire du systĂšme. Aussi, la comparaison de l'utilisation mĂ©moire du driver natif MySQL et de la bibliothĂšque cliente MySQL devient difficile. La bibliothĂšque cliente MySQL appelle directement le gestionnaire mĂ©moire du systĂšme d'exploitation, et donc, les effets peuvent ĂȘtre vus immĂ©diatement au niveau du systĂšme d'exploitation.
Toutes les limitations mémoire réalisées par PHP affectent également le driver natif MySQL. Ceci peut causer des erreurs de dépassement mémoire lors de la récupération de jeux de résultats trop importants, excédant la taille de la mémoire restante disponible pour PHP. En raison du fait que la bibliothÚque cliente MySQL n'utilise pas les fonctions de gestion mémoire de PHP, elle ne prend en compte aucune limitation mémoire définie par PHP. Lors de l'utilisation de la bibliothÚque cliente MySQL, suivant le modÚle de déploiement, l'empreinte mémoire du processus PHP peut s'accroitre et dépasser la limite mémoire imposée par PHP. De plus, les scripts PHP peuvent analyser des jeux de résultats plus importants, allouant ainsi plus de mémoire pour le jeu de résultats que le contrÎle du moteur PHP ne l'autorise.
Les fonctions de gestion mémoire de PHP sont appelées par le driver natif MySQL via un gestionnaire léger. Entre autres, ce gestionnaire rend le débogage facile.
Gestion des jeux de résultats
Les différents serveurs MySQL et les différents clients APIs se différencient suivant la mise en mémoire tampon ou non des jeux de résultats. Les jeux de résultats qui ne sont pas mis en mémoire tampon sont transférés ligne par ligne depuis MySQL vers le client, et le client va parcourir les résultats. Les résultats qui sont mis en mémoire tampon sont récupérés en entier par la bibliothÚque cliente avant de les passer au client.
Le driver natif MySQL utilise des flux PHP pour la communication réseau avec le serveur MySQL. Les résultats envoyés par MySQL sont récupérés depuis la mémoire tampon des flux réseau PHP dans la mémoire tampon de résultats de mysqlnd. La mémoire tampon de résultats est composée de zvals. Dans une étape suivante, les résultats sont rendus disponibles au script PHP. Le transfert final depuis la mémoire tampon des résultats dans les variables PHP impacte la consommation mémoire et cela devient trÚs visible lors de l'utilisation de jeux de résultats mis en mémoire tampon.
Par dĂ©faut, le driver natif MySQL tente de ne pas conserver en mĂ©moire deux fois les rĂ©sultats mis en mĂ©moire tampon. Les rĂ©sultats sont conservĂ©s qu'une seule fois dans la mĂ©moire tampon interne de rĂ©sultats, ainsi que dans leur zvals. Lorsque les rĂ©sultats sont rĂ©cupĂ©rĂ©s dans les variables PHP par le script PHP, les variables vont rĂ©fĂ©rencer la mĂ©moire tampon interne de rĂ©sultats. Les rĂ©sultats de requĂȘtes de base de donnĂ©es ne sont pas copiĂ©s et sont conservĂ©s en mĂ©moire seulement une fois. Lorsqu'un utilisateur modifie le contenu d'une variable contenant un rĂ©sultat de base de donnĂ©es, une opĂ©ration de copie sur Ă©criture doit ĂȘtre effectuĂ©e pour Ă©viter de changer la mĂ©moire tampon interne de rĂ©sultat rĂ©fĂ©rencĂ©e. Le contenu de la mĂ©moire tampon ne doit pas ĂȘtre modifiĂ© parce que l'utilisateur peut dĂ©cider de lire le jeu de rĂ©sultat une seconde fois. L'opĂ©ration de copie sur Ă©criture est implĂ©mentĂ©e en utilisant un gestionnaire de liste de rĂ©fĂ©rence additionnel, ainsi que l'utilisation des compteurs de rĂ©fĂ©rence zvals standard. L'opĂ©ration de copie sur Ă©criture doit Ă©galement ĂȘtre effectuĂ©e si l'utilisateur lit un jeu de rĂ©sultats dans les variables PHP et libĂšre un jeu de rĂ©sultat avant que les variables ne soient supprimĂ©es.
D'une maniĂšre gĂ©nĂ©rale, ce mĂ©canisme fonctionne bien pour les scripts qui lisent un jeu de rĂ©sultats une seule fois, et ne modifient pas les variables contenant les rĂ©sultats. Son inconvĂ©nient majeur est la surcharge mĂ©moire causĂ©e par le gestionnaire de rĂ©fĂ©rence additionnel, qui vient principalement du fait que les variables utilisateurs contenant les rĂ©sultats ne peuvent ĂȘtre entiĂšrement libĂ©rĂ©es tant que le gestionnaire de rĂ©fĂ©rence mysqlnd n'arrĂȘte pas de les rĂ©fĂ©rencer. Le driver natif MySQL supprime la rĂ©fĂ©rence aux variables utilisateurs lorsque le jeu de rĂ©sultat est libĂ©rĂ© ou qu'une opĂ©ration de copie sur Ă©criture est effectuĂ©e. Un observateur peut voir la consommation mĂ©moire totale croĂźtre tant que le jeu de rĂ©sultat n'est pas libĂ©rĂ©. Utiliser les statistiques pour vĂ©rifier si un script libĂšre le jeu de rĂ©sultats explicitement, ou si le driver le libĂšre implicitement, faisant ainsi que la mĂ©moire soit utilisĂ©e plus longtemps que nĂ©cessaire. Les statistiques peuvent aussi aider Ă voir les opĂ©rations de copie sur Ă©criture.
Un script PHP lisant beaucoup de petites lignes d'un jeu de résultat mis en mémoire tampon
en utilisant des lignes de code comme while ($row = $res->fetch_assoc()) { ... }
peut optimiser la consommation mémoire en demandant une copie plutÎt que
des références. Malgré le fait que demander des copies signifie conserver deux
fois le résultat en mémoire, cela autorise PHP à libérer la copie contenue dans
$row sachant que le jeu de rĂ©sultats est en train d'ĂȘtre parcouru
et avant de libĂ©rer le jeu de rĂ©sultats lui-mĂȘme. Sur un serveur chargĂ©,
l'optimisation de l'utilisation mémoire peut améliorer la performance systÚme
globale bien que pour un script individuel, l'approche de la copie peut ĂȘtre plus
lente en raison des opérations supplémentaires d'allocation et de copie mémoire.
Surveillance et débogage
Il existe plusieurs façons de surveiller l'utilisation mĂ©moire du driver natif MySQL. Si le but est d'obtenir une vue rapide haut niveau, ou de vĂ©rifier la mĂ©moire efficiente des scripts PHP, alors vĂ©rifiez les statistiques collectĂ©es par la bibliothĂšque. Elles permettent, par exemple, de voir les requĂȘtes SQL qui gĂ©nĂšrent plus de rĂ©sultats que d'analyses par un script PHP.
La trace de dĂ©bogage dans l'historisation peut ĂȘtre configurĂ©e pour enregistrer les appels au gestionnaire mĂ©moire. Ceci peut aider Ă voir quand la mĂ©moire est allouĂ©e ou libĂ©rĂ©e. Cependant, la taille des morceaux mĂ©moire demandĂ©s peut ne pas y ĂȘtre listĂ©e.
Les versions rĂ©centes du driver natif MySQL tentent d'Ă©muler des situations de dĂ©passement mĂ©moire alĂ©atoire. Ceci est seulement utile aux dĂ©veloppeurs C de la bibliothĂšque, ou aux dĂ©veloppeurs du plugin mysqlnd. Veuillez chercher dans le code source pour les options de configuration de PHP correspondant, ainsi que pour obtenir plus de dĂ©tails sur ce mĂ©canisme. Cette fonctionnalitĂ© est considĂ©rĂ©e comme privĂ©e, et peut ĂȘtre modifiĂ©e Ă tout moment sans aucun avertissement.