Ein umfassender Leitfaden zur mysqli_thread_safe-Funktion in PHP
Erfahren Sie, was Thread-Sicherheit in PHP bedeutet, warum es eine Compile-Zeit-Einstellung ist und wie Sie sie in Ihrer Umgebung prüfen.
Bei der Arbeit mit MySQL-Datenbanken in PHP über die mysqli-Extension stellt sich häufig die Frage: „Ist mysqli Thread-sicher, und gibt es eine Funktion mysqli_thread_safe(), die ich aufrufen kann, um das zu prüfen?"
Die kurze Antwort lautet: mysqli_thread_safe() ist keine Funktion in PHP, und Thread-Sicherheit ist nichts, das man zur Laufzeit abfragt. Es ist eine Eigenschaft, die sich danach richtet, wie Ihr PHP-Binary kompiliert wurde. Dieser Leitfaden erklärt, was „Thread-sicher" für PHP eigentlich bedeutet, warum die Thread-Sicherheit von mysqli eine Compile-Zeit-Entscheidung ist, wann sie in der Praxis relevant ist und wie Sie sie in Ihrer Umgebung prüfen können.
Was „Thread-sicher" in PHP bedeutet
Ein Programm ist Thread-sicher, wenn mehrere Threads denselben Code gleichzeitig ausführen können, ohne gemeinsam genutzte Daten zu beschädigen. Bei einem Thread-sicheren Build schützt die PHP-Engine den internen globalen Zustand (die Symboltabelle, den Speicher-Manager, Extension-Globals usw.), damit zwei Threads, die innerhalb desselben Prozesses ausgeführt werden, sich nicht gegenseitig ihre Daten überschreiben.
PHP wird in zwei Varianten ausgeliefert, die beim Kompilieren des Binaries festgelegt werden:
- ZTS (Zend Thread Safety) — auch als Thread Safe (TS)-Build bezeichnet. Die Engine fügt Locking und pro-Thread-Kopien des globalen Zustands hinzu, damit PHP innerhalb eines Mehrthread-Host-Prozesses laufen kann.
- NTS (Non-Thread-Safe) — die Engine geht davon aus, dass es eine Anfrage pro Prozess gibt, und überspringt diesen Overhead, wodurch sie schneller läuft.
Sie können zur Laufzeit nicht zwischen beiden wechseln, und es gibt keine mysqli_thread_safe()-Funktion, um den Build-Typ umzuschalten oder abzufragen. Der Build-Typ wird beim Kompilieren durch ./configure --enable-maintainer-zts (oder das plattformäquivalente Kommando) festgelegt.
Warum es eine Compile-Zeit-Einstellung ist, keine Funktion
Viele erwarten eine mysqli_thread_safe()-Funktion, weil einige C-Bibliotheken einen mysql_thread_safe()-Aufruf bereitstellen. PHP bietet keinen solchen Aufruf, weil sich die Antwort für ein gegebenes Binary nie ändert — eine Laufzeitabfrage würde stets denselben Wert zurückgeben. Ob mysqli in Threads sicher ist, ergibt sich direkt aus der ZTS/NTS-Entscheidung, die in den PHP-Build eingebacken ist, sowie aus der zugrunde liegenden Client-Bibliothek (modernes PHP nutzt mysqlnd, den nativen Treiber, der keinen eigenen Thread-Sicherheits-Schalter hat).
Statt eine Funktion aufzurufen, untersuchen Sie daher den Build.
Wann Thread-Sicherheit tatsächlich relevant ist
Für die große Mehrheit der PHP-Anwendungen sollten Sie den NTS-Build verwenden, und Thread-Sicherheit ist kein Thema:
| Setup | Zu verwendender Build | Warum |
|---|---|---|
| Nginx + PHP-FPM | NTS | Jeder Worker ist ein Single-Thread-Prozess; keine gemeinsamen Threads. |
Apache mit mpr_prefork | NTS | Jede Anfrage erhält einen eigenen Prozess. |
| CLI-Skripte, Cron-Jobs | NTS | Ein Prozess, ein Thread. |
Apache mit worker / event MPM + mod_php | ZTS | mod_php läuft innerhalb der Thread-Worker von Apache. |
Extensions wie parallel / pthreads (veraltet) | ZTS | Sie erzeugen PHP-Threads in einem Prozess. |
Die klassische Falle in der Praxis ist Apache + mod_php auf einem Thread-MPM: Wenn Sie ein nicht-Thread-sicheres PHP in ein Thread-basiertes Apache laden, kann der Server unter Last abstürzen oder Daten korrumpieren. Der Einsatz von PHP-FPM anstelle von mod_php umgeht dieses Problem vollständig, weshalb FPM + NTS der moderne Standard-Deployment ist. Wie Builds ausgewählt werden, erfahren Sie im PHP-Installationsleitfaden.
Umgang mit mysqli in einem Mehrthread-Kontext
Selbst bei einem korrekt kompilierten ZTS-PHP ist das mysqli-Verbindungsobjekt selbst nicht dafür gedacht, zwischen Threads geteilt zu werden. Ein mysqli-Link enthält gepufferte Ergebnisse, den Zustand von Prepared Statements und einen offenen Socket — die gleichzeitige Nutzung aus zwei Threads führt zu Fehlern wegen falscher Befehlsreihenfolge oder zu falschen Ergebnissen.
Die Regel ist einfach: eine Verbindung pro Thread. Öffnen Sie die Verbindung innerhalb des Threads, der sie nutzt, anstatt ein gemeinsames Handle weiterzugeben.
<?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.
}Grundlegendes zum Öffnen und Prüfen einer Verbindung finden Sie unter Mit mysqli zu MySQL verbinden und mysqli_connect_errno().
So prüfen Sie die Thread-Sicherheit in Ihrer Umgebung
Da es keine Laufzeitfunktion gibt, verwenden Sie eine der folgenden Methoden, um die Build-Einstellung zu lesen.
Mit phpinfo()
Erstellen Sie ein einzeiliges Skript und öffnen Sie es im Browser oder führen Sie es über die CLI aus:
<?php
phpinfo();Suchen Sie in der Ausgabe die oberste Tabelle und achten Sie auf die Zeile Thread Safety (sie befindet sich in der Nähe der Zend Engine / Build-Informationen). Der Wert ist entweder enabled (ZTS) oder disabled (NTS).
Prüfung über die Kommandozeile
Filtern Sie vom Terminal aus die vollständige Konfigurationsausgabe:
php -i | grep "Thread Safety"Dies gibt eine der folgenden Zeilen aus:
Thread Safety => enabled
Thread Safety => disabledIm laufenden PHP-Code
Wenn Sie den Wert programmatisch benötigen — zum Beispiel für eine Diagnoseseite — lesen Sie die Konstante PHP_ZTS aus, anstatt nach einer nicht existierenden Funktion zu suchen:
<?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";Dies ist der korrekte, unterstützte Ersatz für den imaginären mysqli_thread_safe()-Aufruf.
Häufige Fehler
mysqli_thread_safe()aufrufen — diese Funktion existiert nicht und wirft einenError: Call to undefined function. Verwenden Sie stattdessenPHP_ZTSoderphpinfo().- Eine
mysqli-Verbindung zwischen Threads teilen — öffnen Sie stets eine separate Verbindung pro Thread. - Ein NTS-PHP in ein Thread-basiertes Apache-MPM laden — stimmen Sie den Build auf den Server ab oder wechseln Sie zu PHP-FPM.
- Davon ausgehen, dass ZTS „besser" ist — es ist langsamer und wird nur für wirklich Thread-basierte Hosts benötigt; bevorzugen Sie andernfalls NTS.
Fazit
mysqli_thread_safe() ist eine Funktion, die nicht existiert. Thread-Sicherheit in PHP wird zur Compile-Zeit durch die Zend Thread Safety (ZTS)-Entscheidung festgelegt und nicht durch einen Laufzeit-Aufruf umgeschaltet oder abgefragt. Die meisten modernen Stacks (Nginx/Apache-prefork + PHP-FPM) verwenden den schnelleren NTS-Build und benötigen nie ZTS. Wenn Sie es prüfen müssen, lesen Sie es mit phpinfo(), php -i | grep "Thread Safety" oder der Konstanten PHP_ZTS aus — und geben Sie jedem Thread stets seine eigene mysqli-Verbindung, um Datenkonsistenz zu gewährleisten.