aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Serveur de Jeu

MySQL Connection Pool : guide de gestion des connexions

Sur un serveur de jeu chargé ou une application web à fort trafic, un MySQL connection pool (pool de connexions) est l'un des moyens les plus économiques d'améliorer les performances. La raison : ouvrir et fermer une connexion neuve pour chaque opération de base de données est bien plus coûteux qu'il n'y paraît : handshake TCP, authentification, négociation du jeu de caractères et allocation d'un thread côté serveur. Si tout cela se répète à chaque requête, vous finissez par dépenser plus de temps et de CPU dans la mise en place que dans les requêtes elles-mêmes. Cet article explique ce qu'est un pool de connexions, pourquoi et comment il réduit la charge serveur, et comment le configurer correctement dans différents langages.

Pourquoi ouvrir une connexion coûte-t-il cher ?

Quand vous appelez mysql_real_connect ou créez un nouvel objet PDO, voici ce qui se passe en coulisses :

  • Une connexion TCP est établie entre le client et le serveur (handshake en trois temps ; latence d'aller-retour supplémentaire sur un hôte distant).
  • MySQL envoie un paquet de handshake, le client répond avec un identifiant/mot de passe, et le serveur l'authentifie.
  • Si SSL/TLS est activé, un handshake de chiffrement supplémentaire a lieu.
  • Le serveur alloue un thread pour servir la connexion et initialise les variables de session.

Pour une seule connexion cela peut prendre quelques millisecondes, mais sur un serveur traitant des centaines de requêtes par seconde, payer ce coût à chaque requête gonfle la latence et vous rapproche vite de la limite max_connections de MySQL. C'est précisément là qu'intervient le pool de connexions : il ouvre les connexions une fois et, au lieu de les fermer après usage, il les renvoie dans le pool, de sorte que la requête suivante réutilise une connexion prête.

Que fait exactement un pool de connexions ?

Un pool de connexions est un composant qui conserve en mémoire un ensemble de connexions de base de données pré-ouvertes et prêtes à l'emploi. Quand l'application demande une connexion, le pool en prête une inactive ; une fois le travail terminé, la connexion n'est pas fermée mais rendue au pool. Les réglages typiques sont :

  • Taille minimale du pool : le plus petit nombre de connexions à garder ouvertes en permanence (évite la latence de démarrage à froid).
  • Taille maximale du pool : le plus grand nombre de connexions autorisées simultanément ; elle doit rester sous la max_connections de MySQL.
  • Idle timeout : la durée pendant laquelle une connexion inutilisée est conservée avant fermeture.
  • Validation de connexion : vérifier qu'une connexion est toujours vivante avant de la fournir (souvent un simple ping ou SELECT 1).

Résultat : le coût du handshake n'est payé qu'autant de fois que la taille du pool sur toute la durée de vie de l'application, et non pour des milliers de requêtes. Cela réduit la latence par requête et élimine presque entièrement la charge de création/destruction de threads sur le serveur MySQL.

PHP / Laravel : connexions persistantes

Le modèle classique de PHP « chaque requête repart de zéro » complique un pool traditionnel, car le processus meurt à la fin de la requête. La solution, ce sont les connexions persistantes, qui maintiennent la connexion vivante tant que les processus PHP-FPM vivent. Avec PDO :

$pdo = new PDO($dsn, $user, $pass, [
    PDO::ATTR_PERSISTENT => true,
    PDO::ATTR_ERRMODE    => PDO::ERRMODE_EXCEPTION,
]);

Dans Laravel, vous faites de même dans config/database.php :

'mysql' => [
    'driver'  => 'mysql',
    // ...
    'options' => [
        PDO::ATTR_PERSISTENT => true,
    ],
],

Une mise en garde : les connexions persistantes gardent une connexion distincte pour chaque worker PHP-FPM. Si votre nombre de workers est élevé, le total des connexions peut dépasser la limite de MySQL. Planifiez ensemble votre nombre de workers et max_connections. Si vous voulez un vrai pool (contrôle de taille, vérifications de santé), placer ProxySQL devant vos processus PHP est une solution plus robuste.

Node.js : un vrai exemple de pool

Comme Node est mono-processus et à longue durée de vie, un pool de connexions s'y intègre naturellement. Avec la bibliothèque mysql2 :

const mysql = require('mysql2/promise');

const pool = mysql.createPool({
  host: '127.0.0.1',
  user: 'game',
  password: process.env.DB_PASS,
  database: 'server',
  connectionLimit: 20,
  waitForConnections: true,
  queueLimit: 0,
});

const [rows] = await pool.query(
  'SELECT level FROM players WHERE id = ?', [playerId]
);

pool.query() prend une connexion du pool à chaque appel, exécute la requête et rend la connexion automatiquement. Pour les opérations nécessitant la même connexion, comme les transactions, vous en récupérez une manuellement avec pool.getConnection() et la rendez avec connection.release() à la fin — oublier de libérer est l'erreur la plus fréquente qui épuise un pool.

Le côté serveur de jeu (C++)

Sur un serveur de jeu C++ basé sur Metin2 ou maison, il n'y a généralement pas d'ORM tout prêt ; vous gérez le pool vous-même. La logique est la même : au démarrage, vous ouvrez N connexions et les placez dans une file thread-safe ; quand un thread doit exécuter une requête, il en retire une de la file et la remet une fois terminé. Points clés :

  • Sécurité des threads : protégez l'accès au pool avec un mutex ou une file sans verrou. Deux threads ne peuvent pas utiliser la même connexion MySQL en même temps.
  • Reconnexion : quand wait_timeout expire, MySQL ferme la connexion inactive et vous obtenez une erreur « MySQL server has gone away ». Vérifiez avec mysql_ping() avant de la fournir, et reconnectez si elle est morte.
  • Dimensionnement : ajustez le pool au nombre de threads DB du cœur du jeu ; plus de connexions que nécessaire ne fait que gaspiller la mémoire de MySQL.

Bien dimensionner le pool

L'erreur la plus fréquente est de croire que « plus de connexions, c'est toujours mieux ». C'est l'inverse : trop de connexions simultanées ralentissent les choses en augmentant les changements de contexte et la contention de verrous dans MySQL. Un bon point de départ est un pool relativement petit basé sur le nombre de cœurs CPU et la concurrence disque (pour la plupart des applications, quelques connexions par cœur suffisent). Vérifiez en mesurant :

SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Threads_running';
SHOW STATUS LIKE 'Max_used_connections';

Si Threads_running est constamment élevé, le goulot d'étranglement n'est pas le pool mais vos requêtes ; corrigez d'abord les requêtes lentes et les index manquants. Si Max_used_connections bute contre max_connections, soit vous abaissez les limites du pool, soit vous avez réellement besoin de plus de capacité.

Questions fréquentes

MySQL dispose-t-il d'un pool de connexions intégré ?

Non, le pool de connexions classique est un concept côté client. Côté serveur, MySQL Enterprise et MariaDB proposent un plugin « thread pool » ; il sert les connexions avec un petit nombre de threads mais ne supprime pas le coût d'établissement d'une connexion. Les deux résolvent des problèmes différents : le thread pool s'attaque à l'explosion des threads sur le serveur, le pool de connexions au coût de mise en place côté client.

Une connexion persistante est-elle la même chose qu'un pool de connexions ?

Pas tout à fait. Une connexion persistante évite de fermer une connexion après une requête et la réutilise, mais la gestion de la taille et de la santé est limitée. Un vrai pool offre des politiques comme taille minimale/maximale, idle timeout, vérifications de santé et mise en file d'attente. En PHP, un middleware comme ProxySQL sert à obtenir un pool plus robuste.

Quand ai-je besoin de ProxySQL ?

ProxySQL a du sens lorsque vous avez plusieurs serveurs d'application et souhaitez plafonner de façon centralisée le nombre total de connexions, router les requêtes ou séparer lectures et écritures. Pour les petits projets mono-serveur, un pool intégré à l'application suffit généralement.

Vos connexions de base de données étouffent votre serveur ? Si vous avez besoin d'aide pour la mise en place d'un pool de connexions, son dimensionnement ou le réglage côté MySQL pour votre serveur de jeu ou votre projet web, contactez-moi ; j'examinerai votre configuration actuelle et établirai un plan d'amélioration concret.

Bu kategorideki tüm yazılar →

Devamı için