Guide complet sur la fonction mysqli_thread_safe en PHP
Découvrez ce que signifie la sécurité des threads en PHP, pourquoi mysqli_thread_safe n'existe pas et comment vérifier votre configuration.
Lorsque vous travaillez avec des bases de données MySQL en PHP via l'extension mysqli, une question revient souvent : « mysqli est-il thread-safe, et existe-t-il une fonction mysqli_thread_safe() que l'on peut appeler pour le vérifier ? »
La réponse courte est que mysqli_thread_safe() n'est pas une fonction PHP, et la sécurité des threads n'est pas quelque chose que l'on interroge à l'exécution. C'est une propriété liée à la façon dont votre binaire PHP a été compilé. Ce guide explique ce que « thread-safe » signifie réellement pour PHP, pourquoi la sécurité des threads de mysqli est une décision prise à la compilation, quand cela importe en pratique, et comment le vérifier dans votre environnement.
Ce que « Thread-Safe » signifie en PHP
Un programme est thread-safe lorsque plusieurs threads peuvent exécuter le même code simultanément sans corrompre les données partagées. Dans une version thread-safe, le moteur PHP protège l'état global interne (la table des symboles, le gestionnaire de mémoire, les variables globales des extensions, etc.) afin que deux threads s'exécutant dans le même processus ne puissent pas écraser mutuellement leurs données.
PHP est livré en deux variantes, décidées lors de la compilation du binaire :
- ZTS (Zend Thread Safety) — aussi appelée version Thread Safe (TS). Le moteur ajoute des verrous et des copies par thread de l'état global afin que PHP puisse s'exécuter dans un processus hôte multi-threadé.
- NTS (Non-Thread-Safe) — le moteur suppose une requête par processus et évite cette surcharge, ce qui le rend plus rapide.
Il est impossible de basculer entre ces deux modes à l'exécution, et il n'existe pas de mysqli_thread_safe() pour l'activer ou le signaler. Le type de version est fixé lors du choix de ./configure --enable-maintainer-zts (ou l'équivalent sur la plateforme) pendant la compilation.
Pourquoi c'est un paramètre de compilation, pas une fonction
Les gens s'attendent à une fonction mysqli_thread_safe() parce que certaines bibliothèques C exposent un appel mysql_thread_safe(). PHP n'en fournit pas, car la réponse ne change jamais pour un binaire donné — l'interroger à l'exécution retournerait toujours la même valeur. La question de savoir si mysqli est sûr dans les threads est héritée directement du choix ZTS/NTS intégré dans la version PHP, plus la bibliothèque cliente sous-jacente (les versions modernes de PHP utilisent mysqlnd, le pilote natif, qui n'a pas de paramètre de sécurité des threads séparé).
Ainsi, au lieu d'appeler une fonction, vous inspectez la version.
Quand la sécurité des threads est vraiment importante
Pour la grande majorité des applications PHP, vous devriez utiliser la version NTS et la sécurité des threads n'est pas un problème :
| Configuration | Version à utiliser | Pourquoi |
|---|---|---|
| Nginx + PHP-FPM | NTS | Chaque worker est un processus mono-threadé ; pas de threads partagés. |
Apache avec mpr_prefork | NTS | Chaque requête obtient son propre processus. |
| Scripts CLI, tâches cron | NTS | Un processus, un thread. |
Apache avec worker / event MPM + mod_php | ZTS | mod_php s'exécute dans les workers threadés d'Apache. |
Extensions comme parallel / pthreads (legacy) | ZTS | Elles créent des threads PHP dans un processus. |
Le piège classique dans le monde réel est Apache + mod_php sur un MPM threadé : si vous chargez un PHP non thread-safe dans un Apache threadé, le serveur peut planter ou corrompre des données sous charge. Utiliser PHP-FPM à la place de mod_php contourne entièrement ce problème, ce qui explique pourquoi FPM + NTS est le déploiement moderne standard. Consultez le guide d'installation PHP pour savoir comment les versions sont choisies.
Gérer mysqli dans un contexte multi-threadé
Même sur un PHP ZTS correctement compilé, l'objet de connexion mysqli lui-même n'est pas destiné à être partagé entre les threads. Un lien mysqli contient des résultats en mémoire tampon, l'état des requêtes préparées, et un socket ouvert — une utilisation concurrente depuis deux threads produit des erreurs de commandes hors synchronisation ou des résultats incohérents.
La règle est simple : une connexion par thread. Ouvrez la connexion dans le thread qui l'utilise plutôt que de passer un handle partagé.
<?php
// Each worker/thread creates and owns its own connection.
function runWorkerTask(int $workerId): void
{
// New, independent connection for THIS thread.
$db = new mysqli('localhost', 'user', 'password', 'shop');
if ($db->connect_errno) {
// Handle per-thread connection failure locally.
error_log("Worker {$workerId} failed: {$db->connect_error}");
return;
}
$result = $db->query('SELECT COUNT(*) AS total FROM orders');
$row = $result->fetch_assoc();
echo "Worker {$workerId} sees {$row['total']} orders\n";
$db->close(); // Release the connection when the thread is done.
}Pour les bases de l'ouverture et de la vérification d'une connexion, consultez Se connecter à MySQL avec mysqli et mysqli_connect_errno().
Comment vérifier la sécurité des threads dans votre environnement
Comme il n'existe pas de fonction à l'exécution, utilisez l'une de ces méthodes pour lire le paramètre de version.
Utiliser phpinfo()
Créez un script d'une ligne et ouvrez-le dans le navigateur, ou exécutez-le depuis la ligne de commande :
<?php
phpinfo();Dans la sortie, trouvez le tableau principal et regardez la ligne Thread Safety (elle se trouve près des informations sur le Zend Engine / la version). Elle affiche soit enabled (ZTS) soit disabled (NTS).
Vérification en ligne de commande
Depuis un terminal, filtrez le dump de configuration complet :
php -i | grep "Thread Safety"Ceci affiche l'un des résultats suivants :
Thread Safety => enabled
Thread Safety => disabledDans le code PHP en cours d'exécution
Si vous voulez la valeur par programmation — pour une page de diagnostic, par exemple — lisez la constante PHP_ZTS au lieu de chercher une fonction inexistante :
<?php
// PHP_ZTS is 1 on a Thread Safe (ZTS) build, 0 on a Non-Thread-Safe (NTS) build.
echo PHP_ZTS === 1 ? "Thread-safe (ZTS) build\n" : "Non-thread-safe (NTS) build\n";C'est le remplacement correct et pris en charge de l'appel imaginaire mysqli_thread_safe().
Erreurs courantes
- Appeler
mysqli_thread_safe()— cette fonction n'existe pas et lève uneError: Call to undefined function. UtilisezPHP_ZTSouphpinfo()à la place. - Partager une connexion
mysqlientre les threads — ouvrez toujours une connexion séparée par thread. - Charger un PHP NTS dans un MPM Apache threadé — faites correspondre la version au serveur, ou passez à PHP-FPM.
- Supposer que ZTS est « meilleur » — il est plus lent et n'est nécessaire que pour les hôtes véritablement threadés ; préférez NTS dans les autres cas.
Conclusion
mysqli_thread_safe() est une fonction qui n'existe pas. La sécurité des threads en PHP est fixée à la compilation par le choix Zend Thread Safety (ZTS), et non activée ou signalée par un appel à l'exécution. La plupart des stacks modernes (Nginx/Apache-prefork + PHP-FPM) utilisent la version NTS plus rapide et n'ont jamais besoin de ZTS. Lorsque vous devez vérifier, lisez-le avec phpinfo(), php -i | grep "Thread Safety", ou la constante PHP_ZTS — et donnez toujours à chaque thread sa propre connexion mysqli pour maintenir la cohérence des données.