Dans PDO, une connexion peut être rendue persistante à l'aide de l' PDO::ATTR_PERSISTENT
attribut. Selon le manuel php -
Les connexions persistantes ne sont pas fermées à la fin du script, mais sont mises en cache et réutilisées lorsqu'un autre script demande une connexion en utilisant les mêmes informations d'identification. Le cache de connexion persistant vous permet d'éviter la surcharge liée à l'établissement d'une nouvelle connexion chaque fois qu'un script a besoin de parler à une base de données, ce qui se traduit par une application Web plus rapide.
Le manuel recommande également de ne pas utiliser de connexion persistante lors de l'utilisation du pilote ODBC PDO, car cela peut gêner le processus de regroupement de connexions ODBC.
Donc, apparemment, il ne semble y avoir aucun inconvénient à utiliser une connexion persistante dans PDO, sauf dans le dernier cas. Cependant, je voudrais savoir s'il y a d'autres inconvénients à utiliser ce mécanisme, c'est-à-dire une situation où ce mécanisme entraîne une dégradation des performances ou quelque chose du genre.
Réponses:
Veuillez lire cette réponse ci - dessous , qui détaille les moyens d'atténuer les problèmes décrits ici.
Les mêmes inconvénients existent en utilisant PDO comme avec toute autre interface de base de données PHP qui effectue des connexions persistantes: si votre script se termine de manière inattendue au milieu des opérations de base de données, la prochaine requête qui obtient la connexion restante reprendra là où le script mort s'est arrêté. La connexion est maintenue ouverte au niveau du gestionnaire de processus (Apache pour mod_php, le processus FastCGI actuel si vous utilisez FastCGI, etc.), pas au niveau PHP, et PHP ne dit pas au processus parent de laisser la connexion mourir lorsque le script se termine anormalement.
Si le script mort a verrouillé des tables, ces tables resteront verrouillées jusqu'à ce que la connexion s'éteigne ou que le prochain script qui obtient la connexion déverrouille les tables lui-même.
Si le script mort était au milieu d'une transaction, cela peut bloquer une multitude de tables jusqu'à ce que le minuteur d'interblocage se déclenche, et même dans ce cas, le minuteur de blocage peut tuer la demande la plus récente au lieu de l'ancienne demande à l'origine du problème.
Si le script mort était au milieu d'une transaction, le script suivant qui obtient cette connexion obtient également l'état de la transaction. Il est très possible (en fonction de la conception de votre application) que le prochain script n'essaie jamais de valider la transaction existante, ou s'engage alors qu'il n'aurait pas dû, ou annule quand il n'aurait pas dû.
C'est la partie visible de l'iceberg. Tout cela peut être atténué dans une certaine mesure en essayant toujours de nettoyer après une connexion sale sur chaque requête de script, mais cela peut être pénible en fonction de la base de données. À moins que vous n'ayez identifié la création de connexions à la base de données comme la seule chose qui constitue un goulot d'étranglement dans votre script (cela signifie que vous avez effectué le profilage de code à l'aide de xdebug et / ou xhprof ), vous ne devriez pas considérer les connexions persistantes comme une solution à quoi que ce soit.
De plus, la plupart des bases de données modernes (y compris PostgreSQL) ont leurs propres méthodes préférées pour effectuer le pool de connexions qui ne présentent pas les inconvénients immédiats des connexions persistantes basées sur PHP.
Pour clarifier un point, nous utilisons des connexions persistantes sur mon lieu de travail, mais pas par choix. Nous rencontrions un comportement de connexion étrange , où la connexion initiale de notre serveur d'application à notre serveur de base de données prenait exactement trois secondes, alors qu'elle aurait dû prendre une fraction de fraction de seconde. Nous pensons que c'est un bogue du noyau. Nous avons renoncé à essayer de le dépanner car cela se produisait au hasard et ne pouvait pas être reproduit à la demande, et notre informatique externalisée n'avait pas la capacité concrète de le localiser.
Quoi qu'il en soit, lorsque les gens de l'entrepôt traitent quelques centaines de pièces entrantes et que chaque pièce prend trois secondes et demie au lieu d'une demi-seconde, nous avons dû agir avant qu'ils ne nous kidnappent tous et nous obligent à les aider. Ainsi, nous avons retourné quelques éléments dans notre monstruosité ERP / CRM / CMS locale et avons expérimenté toutes les horreurs des connexions persistantes de première main. Il nous a fallu des semaines pour dépister tous les petits problèmes subtils et les comportements bizarres qui se sont produits apparemment au hasard. Il s'est avéré que ces erreurs fatales une fois par semaine que nos utilisateurs éliminaient avec diligence de notre application laissaient des tables verrouillées, des transactions abandonnées et d'autres états malheureux et bancaux.
Cette histoire sanglante a un point: elle a cassé des choses que nous ne nous attendions jamais à casser, tout cela au nom de la performance. Le compromis n'en valait pas la peine, et nous attendons avec impatience le jour où nous pourrons revenir aux connexions normales sans émeute de la part de nos utilisateurs.
la source
SELECT orders.* FROM orders LEFT JOIN items USING(item_id)
register_shutdown_function()
. Si le processus meurt, la connexion s'éteint également. Si ce n'est pas le cas, la connexion est réinitialisée à son état propre (par exemple, les transactions ouvertes sont annulées). En cas d'échec, la connexion est fermée et une nouvelle sera ouverte par la prochaine demande au même processus. Il n'est pas nécessaire de diaboliser les connexions persistantes.mysqli_change_user
est probablement la meilleure solution de contournement pour les personnes qui doivent établir des connexions persistantes dans une application non conçue pour traiter des problèmes d'état.En réponse au problème de Charles ci-dessus,
De: http://www.php.net/manual/en/mysqli.quickstart.connections.php -
Une plainte courante concernant les connexions persistantes est que leur état n'est pas réinitialisé avant la réutilisation. Par exemple, les transactions ouvertes et non terminées ne sont pas automatiquement annulées. Mais aussi, les modifications d'autorisation qui se sont produites entre la mise de la connexion dans le pool et sa réutilisation ne sont pas reflétées. Cela peut être considéré comme un effet secondaire indésirable. Au contraire, le nom persistant peut être compris comme une promesse que l'état est persistant.
L'extension mysqli prend en charge les deux interprétations d'une connexion persistante: état persistant et état réinitialisé avant réutilisation. La valeur par défaut est réinitialisée. Avant qu'une connexion persistante ne soit réutilisée, l'extension mysqli appelle implicitement
mysqli_change_user()
pour réinitialiser l'état. La connexion persistante apparaît à l'utilisateur comme si elle venait juste d'être ouverte. Aucun artefact des utilisations précédentes n'est visible.La
mysqli_change_user()
fonction est une opération coûteuse. Pour de meilleures performances, les utilisateurs peuvent souhaiter recompiler l'extension avec l'indicateur de compilationMYSQLI_NO_CHANGE_USER_ON_PCONNECT
défini.Il appartient à l'utilisateur de choisir entre un comportement sûr et des performances optimales. Les deux sont des objectifs d'optimisation valides. Pour faciliter l'utilisation, le comportement sûr a été défini par défaut au détriment des performances maximales.
la source
Les connexions persistantes ne sont une bonne idée que lorsque la connexion à votre base de données prend un temps (relativement) long. De nos jours, ce n'est presque jamais le cas. Le plus gros inconvénient des connexions persistantes est que cela limite le nombre d'utilisateurs que vous pouvez avoir sur votre site: si MySQL est configuré pour n'autoriser que 10 connexions simultanées à la fois, lorsqu'une 11ème personne essaie de naviguer sur votre site, cela ne fonctionnera pas pour eux. .
PDO ne gère pas la persistance. Le pilote MySQL le fait. Il réutilise les connexions quand a) elles sont disponibles et que l'hôte / l'utilisateur / le mot de passe / la base de données correspondent. En cas de changement, il ne réutilisera pas une connexion. Le meilleur effet net des cas est que ces connexions que vous avez seront démarrées et arrêtées si souvent parce que vous avez différents utilisateurs sur le site et que les rendre persistants ne sert à rien.
La chose clé à comprendre à propos des connexions persistantes est que vous ne devez PAS les utiliser dans la plupart des applications Web. Ils semblent séduisants mais ils sont dangereux et pratiquement inutiles.
Je suis sûr qu'il existe d'autres discussions à ce sujet, mais une connexion persistante est dangereuse car elle persiste entre les demandes. Si, par exemple, vous verrouillez une table pendant une demande et que vous ne parvenez pas à la déverrouiller, cette table restera verrouillée indéfiniment. Les connexions persistantes sont également à peu près inutiles pour 99% de vos applications car vous n'avez aucun moyen de savoir si la même connexion sera utilisée entre différentes requêtes. Chaque thread Web aura son propre ensemble de connexions persistantes et vous n'avez aucun moyen de contrôler quel thread gérera quelles requêtes.
La bibliothèque procédurale mysql de PHP, a une fonctionnalité par laquelle les appels ultérieurs à mysql_connect renverront le même lien, plutôt que d'ouvrir une connexion différente (comme on pourrait s'y attendre). Cela n'a rien à voir avec les connexions persistantes et est spécifique à la bibliothèque mysql. AOP ne présente pas un tel comportement
Lien de ressource: lien
En général, vous pouvez l'utiliser comme un "ensemble de règles" approximatif:
OUI , utilisez des connexions persistantes, si:
La base de données s'exécute sur un autre serveur auquel vous accédez via le réseau
Une (une) application accède très souvent à la base de données
NON , n'utilisez pas de connexions persistantes, si:
Votre application n'a besoin d'accéder à la base de données que 100 fois par heure.
Vous avez de très nombreux serveurs Web accédant à un serveur de base de données
L'utilisation de connexions persistantes est beaucoup plus rapide, surtout si vous accédez à la base de données via un réseau. Cela ne fait pas tellement de différence si la base de données s'exécute sur la même machine, mais c'est quand même un peu plus rapide. Cependant - comme son nom l'indique - la connexion est persistante, c'est-à-dire qu'elle reste ouverte, même si elle n'est pas utilisée.
Le problème avec cela est que dans la "configuration par défaut", MySQL n'autorise que 1000 "canaux ouverts" parallèles. Après cela, les nouvelles connexions sont refusées (vous pouvez modifier ce paramètre). Donc, si vous avez - disons - 20 serveurs Web avec chacun 100 clients sur eux, et chacun d'entre eux n'a qu'un accès à une page par heure, des calculs simples vous montreront que vous aurez besoin de 2000 connexions parallèles à la base de données. Cela ne fonctionnera pas.
Ergo: utilisez-le uniquement pour les applications avec beaucoup de demandes.
la source
Lors de mes tests, j'ai eu un temps de connexion de plus d'une seconde à mon hôte local, supposant ainsi que je devrais utiliser une connexion persistante. D'autres tests ont montré qu'il s'agissait d'un problème avec 'localhost':
Résultats des tests en secondes (mesurés par microtime php):
Fait intéressant: le code suivant est aussi rapide que l'utilisation de 127.0.0.1:
$host = gethostbyname('localhost'); // echo "<p>$host</p>"; $db = new PDO("mysql:host=$host;dbname=" . DATABASE . ';charset=utf8', $username, $password, array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
la source
localhost
utilise une connexion socket, la connexion socket est connue pour être mauvaise sur une grande quantité de connexionsLes connexions persistantes devraient augmenter considérablement les performances. Je ne suis pas d'accord avec l'affirmation selon laquelle vous devriez «éviter» la persévérance.
On dirait que les plaintes ci-dessus sont conduites par quelqu'un utilisant des tables MyIASM et piratant leurs propres versions de transactions en saisissant des verrous de table .. Bien sûr, vous allez dans une impasse! Utilisez beginTransaction () de PDO et déplacez vos tables vers InnoDB.
la source
me semble avoir une connexion persistante consommerait plus de ressources système. Peut-être un montant insignifiant, mais quand même ...
la source
L'explication de l'utilisation de connexions persistantes est évidemment de réduire la quantité de connexions qui sont plutôt coûteuses, malgré le fait qu'elles sont considérablement plus rapides avec MySQL par rapport aux autres bases de données.
Le tout premier problème avec les connexions persistantes ...
Si vous créez des milliers de connexions par seconde, vous ne vous assurez normalement pas qu'il reste ouvert pendant très longtemps, contrairement au système d'exploitation. Basé sur le protocole TCP / IP Les ports ne peuvent pas être recyclés instantanément et doivent également investir un certain temps dans l'étape «FIN» en attendant qu'ils puissent être recyclés.
Le 2ème problème ... en utilisant beaucoup de connexions serveur MySQL.
Beaucoup de gens ne réalisent tout simplement pas que vous êtes capable d'augmenter la variable * max_connections * et d'obtenir plus de 100 connexions simultanées avec MySQL, d'autres ont été battus par d'anciens problèmes Linux de l'incapacité de transmettre plus de 1024 connexions avec MySQL.
Permet de parler maintenant des raisons pour lesquelles les connexions persistantes ont été désactivées dans l'extension mysqli. Malgré le fait que vous pouvez abuser des connexions persistantes et obtenir de mauvaises performances, ce qui n'était pas la raison principale. La vraie raison est que vous pouvez avoir beaucoup plus de problèmes avec cela.
Des connexions persistantes ont été mises en PHP à travers MySQL 3.22 / 3.23 lorsque MySQL n'était pas si difficile, ce qui signifie que vous pouvez facilement recycler les connexions sans problème. Cependant, dans les versions ultérieures, une quantité de problèmes est survenue - Si vous recyclez une connexion qui a des transactions non validées, vous rencontrez des problèmes. Si vous recyclez les connexions avec des configurations de jeu de caractères personnalisées, vous êtes à nouveau en danger, ainsi que les variables éventuellement transformées par session.
Un problème avec l'utilisation de connexions persistantes est qu'elle ne s'adapte pas vraiment bien. Pour ceux qui ont 5000 personnes connectées, vous aurez besoin de 5000 connexions persistantes. En dehors de l'exigence de persévérance, vous pouvez avoir la possibilité de servir 10000 personnes avec un nombre similaire de connexions, car elles sont en mesure de partager des connexions individuelles lorsqu'elles ne sont pas avec elles.
la source
Je me demandais simplement si une solution partielle serait d'avoir un pool de connexions à usage unique. Vous pouvez passer du temps à créer un pool de connexions lorsque le système est à faible utilisation, jusqu'à une limite, les distribuer et les tuer lorsqu'ils sont terminés ou expirés. En arrière-plan, vous créez de nouvelles connexions au fur et à mesure qu'elles sont prises. Dans le pire des cas, cela devrait être aussi lent que la création de la connexion sans le pool, en supposant que l'établissement du lien est le facteur limitant?
la source