Question

J'ai un pool de connexions MySQL pour un service de données sur le Web. Quand il commence à une requête, il faut une connexion de la piscine à utiliser. Le problème est que s'il y a eu une pause significative depuis cette connexion particulière a été utilisée, le serveur peut avoir chronométré dehors et fermé sa fin. Je voudrais pouvoir détecter dans le code de gestion de la piscine.

L'astuce est la suivante: L'environnement dans lequel je me codage ne donne qu'une API très abstraite dans la connexion. Je ne peux que fondamentalement exécuter des instructions SQL. Je n'ai pas accès à la prise réelle ou un accès direct à l'API client MySQL.

Alors, la question est: Qu'est-ce que la déclaration de MySQL moins cher que je peux exécuter sur la connexion pour déterminer si elle fonctionne. Par exemple SELECT 1; devrait fonctionner, mais je me demande s'il y a quelque chose d'encore moins cher? Peut-être quelque chose qui ne va même pas à travers le fil, mais il est traité dans le répertoire lib client MySQL et répond efficacement à la même question?

Précision: Je ne suis pas préoccupé de vérifier si le serveur MySQL est en cours d'exécution, ou si elle est la configuration de base de données est suffisante pour répondre aux questions. Si ces choses sont en baisse, le SQL suivante les exécute de service sera obtenir et gérer l'erreur appropriée. Je ne suis vraiment préoccupé par si la connexion TCP est ouverte ... car si le serveur a fermé, le SQL service Web obtiendra une erreur qui signifie « juste reconnecter et essayez à nouveau », et ce serait gênant de faire une fois dans la fange du code de service.

Fermeture: Le hack /* ping */ est exactement le genre de chose que je cherchais, mais hélas est uniquement disponible via JDBC. La lecture de la documentation pour ce hack, il est clair qu'il a été mis là pour exactement la même raison que je le voulais. Pour les curieux, je travaille dans Haskel , en utilisant et href="http://hackage.haskell.org/package/HDBC-mysql" rel="noreferrer"> HDBC-mysql . Je vais demander à l'auteur de HDBC-mysql pour ajouter un moyen d'appeler mysql_ping() soit directement, soit via un hack similaire.

Le DO 1 de Vlad était aussi le genre de chose que je cherchais, et depuis l'autre bidouille n'est pas disponible en dehors de JDBC, je vais l'utiliser.

Merci pour la grande discussion, en particulier @Vlad!

Était-ce utile?

La solution

ne saura pas l'état réel de la connexion sans passer sur le fil , et SELECT 1 est un candidat assez bon (sans doute, vous pouvez trouver une commande plus courte qui prend moins de temps pour analyser, mais par rapport au réseau ou même latence réalimentation ces économies serait insignifiante.)

Cela dit, je dirais que pinger une connexion avant vérifier dehors de la piscine est pas la meilleure approche .

Vous devriez probablement simplement votre gestionnaire de pool de connexion appliquer son propre keep-alive (délai d'attente) politique pour éviter d'être déconnecté par le serveur (à court d'un problème de connectivité intervenir plus grave, ce qui pourrait vous affecter en plein milieu des opérations régulières de toute façon - et que votre gestionnaire de pool de connexion serait incapable d'aider de toute façon), ainsi que afin de ne pas monopoliser la base de données (pensez handles de fichiers et l'utilisation de la mémoire) inutilement .

Il est donc douteux, à mon avis, que les tests de valeur pour l'état de la connectivité avant de vérifier une connexion de la piscine a vraiment. Il peut être le statut valeur de connexion test avant qu'une connexion est vérifiée à l'arrière dans la piscine , mais cela peut être fait implicitement en marquant simplement la connexion comme sale lorsqu'une erreur dure SQL (ou exception équivalente) se fait sentir ( à moins que l'API que vous utilisez déjà un appel expose comme is-bad pour vous.)

Je recommande donc:

  • mettre en œuvre un keep-alive policty côté client
  • ne pas effectuer des contrôles lors de la vérification des connexions de la piscine
  • effectuer des contrôles sales avant qu'une connexion est retournée à la piscine
  • laisser le code d'application pour traiter d'autres (non-timeout) conditions de connexion exceptionnelle

UPDATE

Il ressort de vos commentaires que vous avez vraiment vraiment veulent ping la connexion (je suppose que parce que vous n'avez pas le plein contrôle sur, ou la connaissance, les caractéristiques de délai d'attente sur le serveur MySQL ou intervenir des équipements de réseau tels que des procurations etc.)

Dans ce cas, vous pouvez utiliser DO 1 comme alternative à SELECT 1; il est marginalement plus rapide - plus court pour analyser, et il ne retourne pas de données réelles (bien que vous obtenir les acks TCP, donc vous faire encore l'aller-retour pour valider que le connexion est toujours établie.)

Mise à jour 2

En ce qui concerne post de Joshua, voici les traces de capture de paquets pour différents scénarios:

SELECT 1;
13:51:01.463112 IP client.45893 > server.mysql: P 2270604498:2270604511(13) ack 2531191393 win 1460 <nop,nop,timestamp 2983462950 59680547>
13:51:01.463682 IP server.mysql > client.45893: P 1:57(56) ack 13 win 65306 <nop,nop,timestamp 59680938 2983462950>
13:51:01.463698 IP client.45893 > server.mysql: . ack 57 win 1460 <nop,nop,timestamp 2983462951 59680938>

DO 1;
13:51:27.415520 IP client.45893 > server.mysql: P 13:22(9) ack 57 win 1460 <nop,nop,timestamp 2983488906 59680938>
13:51:27.415931 IP server.mysql > client.45893: P 57:68(11) ack 22 win 65297 <nop,nop,timestamp 59681197 2983488906>
13:51:27.415948 IP client.45893 > server.mysql: . ack 68 win 1460 <nop,nop,timestamp 2983488907 59681197>

mysql_ping
14:54:05.545860 IP client.46156 > server.mysql: P 69:74(5) ack 78 win 1460 <nop,nop,timestamp 2987247459 59718745>
14:54:05.546076 IP server.mysql > client.46156: P 78:89(11) ack 74 win 65462 <nop,nop,timestamp 59718776 2987247459>
14:54:05.546092 IP client.46156 > server.mysql: . ack 89 win 1460 <nop,nop,timestamp 2987247459 59718776>

Comme vous pouvez le voir, à l'exception du fait que le paquet de mysql_ping est de 5 octets au lieu de 9 octets de DO 1;, le nombre de vols aller-retour (et, par conséquent, le réseau induite par la latence) est exactement le même. Le seul coût supplémentaire que vous payez avec DO 1 par opposition à mysql_ping est l'analyse syntaxique de DO 1, qui est trivial.

Autres conseils

Je ne suis pas sûr de ce que l'API que vous utilisez actuellement (ou langue), mais pour Java, il y a une astuce le pilote JDBC peut faire.

La requête de test standard est:

select 1

comme vous l'avez indiqué. Si vous modifiez à:

/* ping */ select 1

le pilote JDBC remarquerez cela, et envoyer un seul paquet au serveur MySQL pour obtenir une réponse.

Je l'ai appris dans un épisode Sun « Deep Dive » intitulé MySQL Conseils pour les développeurs Java avec Mark Matthews .

Même si vous ne l'utilisez Java, peut-être cette même astuce a été mis en œuvre dans d'autres pilotes de MySQL? Je suppose que le serveur aurait besoin d'être au courant de ce paquet spécial pour qu'il puisse envoyer une réponse ...

« Connexion » dans ce cas a des significations multiples. MySQL écoute sur un socket- qui est le niveau du réseau « connexion ». MySQL maintient « les connexions de base de données », qui comprennent un contexte pour l'exécution des requêtes et autres frais généraux.

Si vous voulez juste savoir si le service est à l'écoute, vous devriez être en mesure d'exécuter un appel au niveau du réseau pour voir si le port (ne sais pas ce que la valeur par défaut est) est à l'écoute sur la cible IP. Si vous voulez obtenir le moteur MySQL pour répondre, je pense que votre idée est SELECT 1 Good- il ne fait chercher toutes les données de la base de données, mais ne confirme que le moteur est mis en rotation et de répondre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top