Guia Completo sobre a Função mysqli_thread_safe em PHP
Saiba o que significa thread-safe em PHP, por que mysqli_thread_safe() não existe e como verificar a segurança de threads no seu ambiente.
Ao trabalhar com bancos de dados MySQL em PHP através da extensão mysqli, uma dúvida que surge frequentemente é: "O mysqli é thread-safe e existe uma função mysqli_thread_safe() que posso chamar para verificar?"
A resposta curta é que mysqli_thread_safe() não é uma função em PHP, e a segurança de threads não é algo que se consulta em tempo de execução. É uma propriedade de como seu binário PHP foi compilado. Este guia explica o que "thread-safe" realmente significa para PHP, por que a segurança de threads do mysqli é uma decisão em tempo de compilação, quando isso importa na prática e como verificar no seu ambiente.
O Que "Thread-Safe" Significa em PHP
Um programa é thread-safe quando múltiplas threads podem executar o mesmo código ao mesmo tempo sem corromper dados compartilhados. Em uma compilação thread-safe, o motor PHP protege o estado global interno (a tabela de símbolos, o gerenciador de memória, as variáveis globais das extensões, etc.) para que duas threads executando dentro do mesmo processo não corrompam os dados uma da outra.
PHP é distribuído em dois sabores, decididos quando o binário é compilado:
- ZTS (Zend Thread Safety) — também chamado de compilação Thread Safe (TS). O motor adiciona bloqueios e cópias por thread do estado global para que PHP possa rodar dentro de um processo hospedeiro multi-thread.
- NTS (Non-Thread-Safe) — o motor assume uma requisição por processo e ignora essa sobrecarga, tornando-se mais rápido.
Não é possível alternar entre eles em tempo de execução, e não existe mysqli_thread_safe() para alternar ou reportar isso. O tipo de compilação é fixo quando ./configure --enable-maintainer-zts (ou o equivalente da plataforma) é escolhido durante a compilação.
Por Que É uma Configuração em Tempo de Compilação, Não uma Função
As pessoas esperam uma função mysqli_thread_safe() porque algumas bibliotecas C expõem uma chamada mysql_thread_safe(). PHP não oferece uma, porque a resposta nunca muda para um dado binário — consultá-la em tempo de execução sempre retornaria o mesmo valor. Se mysqli é seguro em threads é herdado diretamente da escolha ZTS/NTS incorporada na compilação PHP, mais a biblioteca cliente subjacente (o PHP moderno usa mysqlnd, o driver nativo, que não tem toggle separado de segurança de threads).
Portanto, em vez de chamar uma função, você inspeciona a compilação.
Quando a Segurança de Threads Realmente Importa
Para a grande maioria das aplicações PHP, você deve usar a compilação NTS e a segurança de threads não é um problema:
| Configuração | Compilação a usar | Por quê |
|---|---|---|
| Nginx + PHP-FPM | NTS | Cada worker é um processo single-thread; sem threads compartilhadas. |
Apache com mpr_prefork | NTS | Cada requisição tem seu próprio processo. |
| Scripts CLI, cron jobs | NTS | Um processo, uma thread. |
Apache com worker / event MPM + mod_php | ZTS | mod_php roda dentro dos workers com threads do Apache. |
ext como parallel / pthreads (legado) | ZTS | Eles criam threads PHP em um processo. |
A armadilha clássica do mundo real é Apache + mod_php em um MPM com threads: se você carregar um PHP não thread-safe em um Apache com threads, o servidor pode travar ou corromper dados sob carga. Usar PHP-FPM em vez de mod_php contorna isso completamente, que é por isso que FPM + NTS é o deployment moderno padrão. Veja o guia de instalação do PHP para saber como as compilações são escolhidas.
Tratando mysqli em um Contexto Multi-Thread
Mesmo em um PHP ZTS corretamente compilado, o objeto de conexão mysqli em si não é destinado a ser compartilhado entre threads. Um link mysqli mantém resultados em buffer, estado de prepared statements e um socket aberto — o uso concorrente de duas threads produz erros de comandos fora de sincronia ou resultados incorretos.
A regra é simples: uma conexão por thread. Abra a conexão dentro da thread que a usa em vez de passar um handle compartilhado.
<?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.
}Para os conceitos básicos de abrir e verificar uma conexão, veja Conectar ao MySQL com mysqli e mysqli_connect_errno().
Como Verificar a Segurança de Threads no Seu Ambiente
Como não há função em tempo de execução, use uma destas opções para ler a configuração da compilação.
Usando phpinfo()
Crie um script de uma linha e abra-o no navegador, ou execute-o a partir da CLI:
<?php
phpinfo();Na saída, encontre a tabela superior e olhe para a linha Thread Safety (fica próximo às informações do Zend Engine / compilação). Ela exibe enabled (ZTS) ou disabled (NTS).
Verificação pela Linha de Comando
Em um terminal, filtre o dump completo da configuração:
php -i | grep "Thread Safety"Isso imprime um dos seguintes:
Thread Safety => enabled
Thread Safety => disabledDentro do Código PHP em Execução
Se você quiser o valor programaticamente — para uma página de diagnósticos, por exemplo — leia a constante PHP_ZTS em vez de procurar uma função inexistente:
<?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";Este é o substituto correto e suportado para a imaginária chamada mysqli_thread_safe().
Erros Comuns
- Chamar
mysqli_thread_safe()— ela não existe e lança umError: Call to undefined function. UsePHP_ZTSouphpinfo()em vez disso. - Compartilhar uma conexão
mysqlientre threads — sempre abra uma conexão separada por thread. - Carregar um PHP NTS em um Apache MPM com threads — corresponda a compilação ao servidor, ou migre para PHP-FPM.
- Assumir que ZTS é "melhor" — é mais lento e só é necessário para hosts genuinamente com threads; prefira NTS caso contrário.
Conclusão
mysqli_thread_safe() é uma função que não existe. A segurança de threads em PHP é fixada em tempo de compilação pela escolha do Zend Thread Safety (ZTS), não alternada ou reportada por uma chamada em tempo de execução. A maioria das stacks modernas (Nginx/Apache-prefork + PHP-FPM) usa a compilação mais rápida NTS e nunca precisa de ZTS. Quando você precisar verificar, leia com phpinfo(), php -i | grep "Thread Safety", ou a constante PHP_ZTS — e sempre dê a cada thread sua própria conexão mysqli para manter os dados consistentes.