Connexions persistantes aux bases de données

Qu'est-ce que les connexions persistantes ?

Les connexions persistantes aux bases de données SQL sont des connexions qui ne se referment pas à la fin du script. Lorsqu'une connexion persistante est demandée, PHP s'assure qu'il n'y a pas une autre connexion identique (qui serait ouverte précédemment, avec le même nom d'hôte, d'utilisateur et le même mot de passe), et si une telle connexion existe, elle est utilisée ; sinon, elle est créée. Une connexion identique est une connexion qui a ouvert le même hôte, avec le même nom et le même mot de passe (s'ils sont nécessaires).

Il n'y a pas de méthode pour demander une connexion spécifique, ou garantir que vous obtenez une connexion existante ou une toute nouvelle (si toutes les connexions sont utilisées, ou si la requête est servie par un autre processus, qui a un ensemble de connexions séparé).

Cela signifie que vous ne pouvez pas utiliser les connexions persistantes PHP pour, par exemple :

  • assigner une session de base de données spécifique à un utilisateur web spécifique
  • créer une grande transaction à travers plusieurs requêtes
  • initier une requête sur une demande et collecter les résultats sur une autre

Les connexions persistantes ne vous donnent aucune fonctionnalité qui n'était pas possible avec des connexions non persistantes.

Requêtes Web

Il existe deux façons pour votre serveur web d'utiliser PHP pour générer des pages web :

La première est d'utiliser PHP comme un CGI (Common Interface Gateway). Lorsque PHP fonctionne de cette manière, une instance de l'interpréteur PHP est créée puis détruite pour chaque page demandée. Étant donné que cet interpréteur est détruit après chaque requête, toutes les ressources acquises (comme une connexion à une base SQL), sont purement et simplement détruites. Dans ce cas vous ne gagnez rien à utiliser des connexions persistantes - elles ne persistent tout simplement pas.

La deuxième méthode, de loin la plus prisée, est d'exécuter PHP-FPM, ou PHP sous la forme d'un module sur un serveur multiprocessus, ce qui revient à dire : Apache. Ces configurations ont généralement un processus (le parent) qui coordonne un ensemble de processus fils, qui servent les fichiers. Lorsque les requêtes parviennent depuis un client, elles sont transmises à un fils disponible. Cela signifie que si un client fait une deuxième requête, il peut être servi par un processus client différent du premier. Les connexions persistantes vous permettent alors de ne vous connecter à une base SQL que la première fois. Lors des connexions ultérieures, les processus fils pourront réutiliser la connexion ouverte précédemment.

Note:

Vous pouvez vérifier quelle méthode vos requêtes web utilisent en vérifiant la valeur de "Server API" dans la sortie de phpinfo() ou la valeur de PHP_SAPI, exécutée depuis une requête web.

Si la valeur de Server API est "CGI" ou "CLI", alors les connexions persistantes ne seront pas utilisées entre les requêtes. Pour toute autre valeur, les connexions persistantes persisteront après chaque requête.

Processus en ligne de commande

Comme PHP en ligne de commande utilise un nouveau processus pour chaque script, les connexions persistantes ne sont pas partagées entre les scripts en ligne de commande, donc il n'y a aucun intérêt à les utiliser dans des scripts transitoires tels que les crons ou les commandes. Cependant, elles peuvent être utiles si, par exemple, vous écrivez un serveur d'applications de longue durée qui sert de nombreuses requêtes ou tâches et que chacune peut avoir besoin de sa propre connexion à la base de données.

Pourquoi les utiliser ?

Les connexions persistantes sont utiles si le coût de création d'une liaison vers votre serveur SQL est élevé. Que ce coût soit réellement élevé ou pas ceci dépend de nombreux facteurs : le type de base de données, cette base est-elle sur le même serveur ou pas, quelle est la charge du serveur de base de données, etc. Si le temps de connexion est long, les connexions persistantes seront bien utiles, car une fois ouverte par un processus fils, la connexion est réutilisable sans avoir à se reconnecter. Si vous avez 20 processus fils, il suffit d'avoir 20 connexions persistantes ouvertes, une par fils.

Inconvénients potentiels : limites de connexion

Notez que les connexions persistantes ont quelques inconvénients si vous hébergez une base de données dont le nombre maximal de connexion risque d'être atteint par les connexions persistantes. Si votre base de données accepte jusqu'à 16 connexions peut être rapidement submergée.

Les connexions persistantes augmenteront généralement le nombre de connexions ouvertes à un moment donné parce que les travailleurs inactifs conserveront les connexions pour les requêtes précédentes qu'ils ont servies. Si un grand nombre de travailleurs est lancé pour gérer un afflux de requêtes, les connexions qu'ils ont ouvertes resteront jusqu'à ce que le travailleur soit tué ou que le serveur de base de données ferme la connexion.

Assurez-vous que le nombre maximal de connexions autorisées par le serveur de base de données est supérieur au nombre maximal de travailleurs de requêtes web (plus toute autre utilisation telle que les crons ou les connexions administratives).

Vérifiez votre documentation de base de données pour des informations sur la gestion des connexions abandonnées ou inactives (timeouts). Des timeouts longs peuvent augmenter considérablement le nombre de connexions persistantes ouvertes à un moment donné.

Inconvénients potentiels : Maintien de l'état de connexion

Certaines extensions de base de données effectuent un nettoyage automatique lorsque la connexion est réutilisée ; d'autres laissent cette tâche à la discrétion du développeur d'application. En fonction de l'extension de base de données choisie et de la conception de l'application, un nettoyage manuel peut être nécessaire avant la fin du script. Les modifications qui peuvent laisser les connexions dans un état inattendu incluent :

  • Base de données sélectionnée / par défaut
  • Verrous de table
  • Transactions non commises
  • Tables temporaires
  • Paramètres ou fonctionnalités spécifiques à la connexion telles que le profilage

Les verrous de table et les transactions qui ne sont pas nettoyés ou fermés peuvent entraîner le blocage indéfini d'autres requêtes et/ou provoquer des modifications inattendues lors de la réutilisation ultérieure de la connexion.

Avoir la mauvaise base de données sélectionnée entraînera la réutilisation de la connexion incapable d'exécuter les requêtes suivantes comme prévu (ou de les exécuter sur la mauvaise base de données si les schémas sont suffisamment similaires).

Si les tables temporaires ne sont pas nettoyées, les requêtes suivantes ne pourront pas recréer la même table.

Vous pouvez implémenter le nettoyage en utilisant des destructeurs de classe ou register_shutdown_function(). Vous pouvez également envisager des proxies de mise en pool de connexions dédiés qui incluent cela dans leur fonctionnalité.

Derniers mots

Étant donné leur comportement et les inconvénients potentiels décrits ci-dessus, vous ne devez pas utiliser les connexions persistantes sans une réflexion approfondie. Elles ne doivent pas être utilisées sans mettre en œuvre des modifications supplémentaires dans votre application et une configuration soigneuse de votre serveur de base de données et de votre serveur web et/ou PHP-FPM.

Considérez des solutions alternatives telles que l'investigation et la correction des causes des surcoûts de création de connexion (par exemple, la désactivation des recherches DNS inverses sur le serveur de base de données), ou des proxies de mise en pool de connexions dédiés.

Pour les API web à fort volume, envisagez d'utiliser des runtimes alternatifs ou des serveurs d'applications de longue durée.

add a note

User Contributed Notes 7 notes

up
22
Tom
15 years ago
There's a third case for PHP: run on a fastCGI interface. In this case, PHP processes are NOT destroyed after each request, and so persistent connections do persist. Set PHP_FCGI_CHILDREN << mysql's max_connections and you'll be fine.
up
14
ambrish at php dot net
15 years ago
In IBM_DB2 extension v1.9.0 or later performs a transaction rollback on persistent connections at the end of a request, thus ending the transaction. This prevents the transaction block from carrying over to the next request which uses that connection if script execution ends before the transaction block does.
up
14
php at alfadog dot net
11 years ago
One additional not regarding odbc_pconnect and possibly other variations of pconnect:

If the connection encounters an error (bad SQL, incorrect request, etc), that error will return with be present in odbc_errormsg for every subsequent action on that connection, even if subsequent actions don't cause another error.

For example:

A script connects with odbc_pconnect.
The connection is created on it's first use.
The script calls a query "Select * FROM Table1".
Table1 doesn't exist and odbc_errormsg contains that error.

Later(days, perhaps), a different script is called using the same parameters to odbc_pconnect.
The connection already exists, to it is reused.
The script calls a query "Select * FROM Table0".
The query runs fine, but odbc_errormsg still returns the error about Table1 not existing.

I'm not seeing a way to clear that error using odbc_ functions, so keep your eyes open for this gotcha or use odbc_connect instead.
up
14
christopher dot jones at oracle dot com
18 years ago
For the oci8 extension it is not true that " [...] when using transactions, a transaction block will also carry over to the next script which uses that connection if script execution ends before the transaction block does.". The oci8 extension does a rollback at the end scripts using persistent connections, thus ending the transaction. The rollback also releases locks. However any ALTER SESSION command (e.g. changing the date format) on a persistent connection will be retained over to the next script.
up
11
ynzhang from lakeheadu canada
16 years ago
It seems that using pg_pconnect() will not persist the temporary views/tables. So if you are trying to create temporary views/tables with the query results and then access them with the next script of the same session, you are out of luck. Those temporary view/tables are gone after each PHP script ended. One way to get around this problem is to create real view/table with session ID as part of the name and record the name&creation time in a common table. Have a garbage collection script to drop the view/table who's session is expired.
up
10
jean_christian at myrealbox dot com
23 years ago
If anyone ever wonders why the number of idle db process (open connections) seems to grow even though you are using persistent connections, here's why:

"You are probably using a multi-process web server such as Apache. Since
database connections cannot be shared among different processes a new
one is created if the request happen to come to a different web server
child process."
up
8
andy at paradigm-reborn dot com
18 years ago
To those using MySQL and finding a lot of leftover sleeping processes, take a look at MySQL's wait_timeout directive. By default it is set to 8 hours, but almost any decent production server will have been lowered to the 60 second range. Even on my testing server, I was having problems with too many connections from leftover persistent connections.
To Top