Atualize os drivers PHP para o SQL Server

Atualize SQLSRV e PDO_SQLSRV juntos para que ambas as extensões usem a mesma família de releases. Os drivers PHP usam o Microsoft ODBC Driver for SQL Server, então verifique os requisitos do sistema antes de atualizar.

Uma atualização altera o código nativo carregado nos processos do PHP. Uma implantação mista pode continuar rodando a versão anterior, falhar na inicialização do PHP ou expor diferentes versões de drivers à CLI e à aplicação web. Faça inventário de cada runtime PHP e mantenha os arquivos e configurações anteriores até a verificação terminar.

Escolha o caminho de upgrade

Instalação atual Instalação de destino Procedure
PIE PIE Execute o PIE com o mesmo executável PHP ou especifique explicitamente php-config, depois verifique cada SAPI
ZIP extraído do Windows arquivo ZIP do Windows Substituir ambas as DLLs versionadas e atualizar as duas entradas de configuração juntas
Windows extraiu o ZIP PIE Instale ambos os pacotes PIE, substitua entradas de DLL versionadas por entradas PIE e remova duplicatas
Arquivo para Linux ou macOS PIE Instale ambos os pacotes PIE, substitua as entradas do nome do arquivo por sqlsrv.so e pdo_sqlsrv.so, e preserve a ordem de carregamento do PDO
Linux ou macOS PIE Nova versão secundária do PHP Instale as novas ferramentas de desenvolvimento do PHP, construa ambas as extensões para essa instalação do PHP e configure cada SAPI separadamente

Não sobrescreva os binários anteriores até ter uma cópia de rollback. Não atualize apenas uma extensão quando o aplicativo usa ambas as APIs.

Antes de atualizar

  1. Grave o executável PHP, arquivo de configuração, arquitetura, modo de segurança de thread e versões atuais dos drivers.

    php --version
    php --ini
    php --ri sqlsrv
    php --ri pdo_sqlsrv
    
  2. Faça backup do php.ini arquivo e de quaisquer arquivos específicos .ini de extensão que carreguem sqlsrv ou pdo_sqlsrv.

  3. Verifique a matriz de suporte para a versão de PHP e o sistema operacional de destino.

  4. Verifique a tabela de compatibilidade ODBC em Requisitos do Sistema. Instale uma versão ODBC suportada antes ou durante a atualização do driver PHP quando a versão de lançamento do driver de destino exigir isso.

  5. Planeje uma reinicialização de todos os processos que carregam o PHP, incluindo o servidor web, o PHP FastCGI Process Manager (PHP-FPM), trabalhadores de fila e trabalhadores de linha de comando de longa duração.

  6. Registre uma linha de base de cada runtime:

    • O que é mostrado por php --ri sqlsrv e php --ri pdo_sqlsrv.
    • O arquivo de configuração foi carregado e o diretório .ini foi verificado.
    • O diretório de extensão e os nomes dos arquivos dos drivers ativos.
    • Um teste de fumaça de aplicação que passa e que usa cada API da qual sua aplicação depende.
  7. Prepare-se para um rollback:

    • Mantenha o tempo de execução PHP anterior disponível se você mudar a versão secundária do PHP. Grave o executável configurado para cada servidor web e worker.
    • Mantenha cópias dos arquivos SQLSRV e PDO_SQLSRV anteriores.
    • Mantenha cópias de cada arquivo alterado php.ini ou arquivo específico da extensão .ini.
    • Registre a versão anterior do pacote ODBC se a atualização mudar essa versão.
    • Defina como parar o tráfego ou workers enquanto arquivos de extensão nativos são substituídos.

Atualize no Windows com PIE

Use o PHP Installer for Extensions (PIE) com o executável PHP que atende à aplicação. Primeiro, baixe e verifique o PIE. Antes de executar qualquer comando de instalação, drene o tráfego da aplicação e pare o servidor web, os processos do FastCGI e os trabalhadores que usam essa instalação em PHP. Impeça que eles reiniciem automaticamente até que ambas as extensões e suas configurações estejam prontas. Mantenha uma sessão de linha de comando separada para o PIE.

Comente temporariamente as entradas existentes das extensões SQLSRV e PDO_SQLSRV na configuração CLI usada pelo PIE. Caso contrário, o processo PHP rodando PIE pode manter as DLLs antigas carregadas e impedir a substituição. Mantenha as extensões pré-requisito do PIE ativadas.

A partir do diretório que contém pie.phar, instale ambos os pacotes separadamente:

php .\pie.phar install microsoft/sqlsrv
php .\pie.phar install microsoft/pdo_sqlsrv

PIE instala php_sqlsrv.dll e php_pdo_sqlsrv.dll. Em toda configuração ativa, substitua entradas ZIP versionadas como extension=php_sqlsrv_85_ts_x64.dll e extension=php_pdo_sqlsrv_85_ts_x64.dll por:

extension=php_sqlsrv.dll
extension=php_pdo_sqlsrv.dll

Ative ambas as entradas e remova entradas duplicadas SQLSRV e PDO_SQLSRV mesmo que o PIE informe que a habilitação automática foi bem-sucedida. Se o servidor web usar uma instalação PHP diferente, repita as mudanças de atualização e configuração para essa instalação.

Reinicie cada processo PHP, então execute php --ri sqlsrv e php --ri pdo_sqlsrv com o executável correspondente. Confirme que ExtensionVer informa a versão alvo para ambos os drivers. Para uma aplicação web, restrinja o acesso à página de diagnóstico antes de criar uma página temporária phpinfo() . Verifique ambos os valores e remova a página.

Atualizar uma instalação ZIP do Windows

  1. Baixe o Windows ZIP da versão de destino na página Microsoft Drivers for PHP for SQL Server releases.

  2. Confirme que os nomes da nova biblioteca de vínculo dinâmico (DLL) correspondem à versão secundária do PHP, à arquitetura e ao modo de segurança de threads. Pare o servidor web PHP ou os processos de trabalho antes de substituir arquivos.

  3. Substitua os arquivos php_sqlsrv_*.dll e php_pdo_sqlsrv_*.dll no diretório de extensão PHP. Mantenha as entradas existentes extension= se os nomes dos arquivos ainda coincidirem. Caso contrário, atualize-os ao mesmo tempo.

  4. Instale ou atualize o driver Microsoft ODBC para SQL Server se o driver PHP de destino exigir uma versão mais recente suportada.

  5. Reinicie todos os processos PHP que usem as DLLs substituídas. Um processo em execução mantém a antiga extensão nativa carregada até que ele termine.

Atualize no Linux ou macOS com PIE

  1. Siga a configuração do PIE e os pré-requisitos da plataforma se o PIE não estiver instalado. Confirme que as ferramentas de desenvolvimento PHP e o pacote de desenvolvimento do ODBC estão instalados. Em uma sessão interativa, o PIE pode solicitar a instalação de ferramentas de build faltantes pelo gerenciador de pacotes da plataforma. Em uma sessão não interativa, instale-os antes de rodar o PIE.

  2. Selecione a instalação do PHP antes de atualizar. Para uma instalação versionada, adicione a opção do --with-php-config PIE a ambos os comandos de instalação. Por exemplo, use pie install --with-php-config=/usr/bin/php-config8.4 microsoft/sqlsrv quando a ferramenta de configuração pretendida for /usr/bin/php-config8.4. Aplique a mesma opção a microsoft/pdo_sqlsrv. Para os executáveis versionados do Alpine, use os comandos de instalação do Alpine.

  3. Interrompa o tráfego da aplicação e pare o servidor web, processos PHP-FPM e trabalhadores que usam essa instalação PHP. Evite que eles reiniciem automaticamente até que ambas as extensões e suas configurações estejam prontas. Mantenha uma sessão de linha de comando separada para o PIE.

    Comente temporariamente as entradas existentes das extensões SQLSRV e PDO_SQLSRV na configuração CLI usada pelo PIE. Mantenha as extensões pré-requisito do PIE ativadas.

  4. Faça upgrade dos dois pacotes separadamente. Esses comandos usam a instalação padrão do PHP do PIE:

    pie install microsoft/sqlsrv
    pie install microsoft/pdo_sqlsrv
    
  5. Verifique todas as configurações ativas da instalação PHP usada pela sua aplicação. Se uma instalação manual anterior usar nomes de arquivo de arquivo como extension=SQLSRV_8.4_NTS.so e extension=PDO_SQLSRV_8.4_NTS.so, substitua essas entradas pelos nomes de arquivo instalados no PIE:

    extension=sqlsrv.so
    extension=pdo_sqlsrv.so
    

    Reative ambas as entradas do driver e remova as duplicatas. Mantenha PDO_SQLSRV em um arquivo de configuração escaneado que carrega após o PDO, conforme descrito em Carregar os drivers no Linux e macOS. Repita essa mudança de configuração para as configurações de linha de comando, PHP-FPM, servidor web e worker que sua aplicação utiliza.

  6. Atualize o driver Microsoft ODBC para SQL Server quando necessário pela versão alvo.

  7. Reinicie cada worker CLI, worker de fila, servidor web e serviço PHP-FPM que usam a instalação atualizada do PHP.

Reinicie e verifique

Substituir um arquivo de extensão não atualiza um processo PHP que já carregou o binário antigo. Reinicie o servidor web, o PHP-FPM e quaisquer processos PHP de longa duração antes de verificar a atualização.

  1. Verifique o runtime de linha de comando:

    php --ri sqlsrv
    php --ri pdo_sqlsrv
    php -m | findstr /I "sqlsrv pdo_sqlsrv"
    

    No Linux ou macOS, substitua o último comando por php -m | grep -E 'sqlsrv|pdo_sqlsrv'.

  2. Para uma aplicação web, restrinja o acesso à página de diagnóstico antes de criar uma página temporária phpinfo() . Verifique o arquivo de configuração carregado, o diretório de extensão e ExtensionVer para ambos os drivers. Confirme que isso ExtensionVer mostra a versão alvo e remova a página.

  3. Execute um teste de fumaça de aplicação existente que exerça tanto SQLSRV quanto PDO_SQLSRV se sua aplicação usar ambos. Mantenha a configuração da conexão inalterada durante essa verificação para que um teste de atualização não teste também uma mudança de conexão não relacionada.

Se um driver falhar ao carregar, compare a versão secundária do PHP, arquitetura, modo de segurança de threads, diretório de extensão e instalação ODBC com os valores registrados antes da atualização.

Verifique tanto as APIs quanto as versões

Salve este programa como verify-driver-upgrade.php:

<?php
$results = [
    'SQLSRV' => [
        'loaded' => extension_loaded('sqlsrv') && function_exists('sqlsrv_connect'),
        'version' => phpversion('sqlsrv'),
    ],
    'PDO_SQLSRV' => [
        'loaded' => extension_loaded('pdo_sqlsrv')
            && in_array('sqlsrv', PDO::getAvailableDrivers(), true),
        'version' => phpversion('pdo_sqlsrv'),
    ],
];

$failed = false;
foreach ($results as $name => $result) {
    $version = $result['version'] === false ? 'unknown' : $result['version'];
    echo "$name: " . ($result['loaded'] ? 'loaded' : 'missing') . ", version $version" . PHP_EOL;
    $failed = $failed || !$result['loaded'] || $result['version'] === false;
}

exit($failed ? 1 : 0);

Execute o programa com o executável da CLI e, temporariamente, em cada runtime web. Confirme se ambas as versões reportadas correspondem à versão que você instalou. Remova a cópia da web após a verificação.

Este programa verifica a camada de extensão PHP. Execute o teste de fumaça da aplicação inalterado depois para verificar o carregamento ODBC, opções de conexão, autenticação, acesso ao banco de dados, tipos PHP retornados e comportamento de limpeza.

Verifique o comportamento do banco de dados antes e depois da atualização

Use o mesmo programa e configurações de conexão antes e depois da atualização. Manter o teste inalterado separa as mudanças de driver das mudanças na aplicação ou na configuração de conexão.

Defina as variáveis de ambiente SQL_SERVER_NAME, SQL_DATABASE, SQL_UID e SQL_PWD para uma conta de teste respondendo aos prompts. Insira os valores brutos, sem aspas de shell ou codificação de driver. Não inclua credenciais em uma linha de comando ou em uma sessão de terminal gravada.

No Windows PowerShell, insira o nome do servidor e do banco de dados, depois use a caixa de diálogo de credenciais ou o prompt para a conta de teste:

$env:SQL_SERVER_NAME = Read-Host "Server name (tcp:<server>,1433)"
$env:SQL_DATABASE = Read-Host "Database name"
$credential = Get-Credential -Message "Enter the database test account"
if ($null -eq $credential) {
    throw "Database test credentials are required."
}
$env:SQL_UID = $credential.UserName
$env:SQL_PWD = $credential.GetNetworkCredential().Password
Remove-Variable credential

No Linux ou macOS, use o Bash. Desative o rastreamento de comandos antes de ler qualquer valor. O prompt de senha não ecoa sua entrada:

set +x
IFS= read -r -p 'Server name (tcp:<server>,1433): ' SQL_SERVER_NAME
IFS= read -r -p 'Database name: ' SQL_DATABASE
IFS= read -r -p 'User name: ' SQL_UID
IFS= read -r -s -p 'Password: ' SQL_PWD
printf '\n'
export SQL_SERVER_NAME SQL_DATABASE SQL_UID SQL_PWD

O ambiente contém a senha em texto simples para que o PHP possa lê-la. Use essas variáveis apenas na sessão de teste, não as imprima e limpe-as após o teste.

Salve este programa como test-driver-upgrade.php. Mantenha os valores do ambiente inalterados. O programa dobra as chaves de fechamento e adiciona chaves externas antes de passar o nome do banco de dados, nome de usuário e senha para o driver. Essa codificação preserva as chaves literais e impede que pontos e vírgula separem as opções de conexão.

<?php
$serverName = getenv('SQL_SERVER_NAME');
$database = getenv('SQL_DATABASE');
$uid = getenv('SQL_UID');
$pwd = getenv('SQL_PWD');

if ($serverName === false || $serverName === ''
    || $database === false || $database === ''
    || $uid === false || $uid === ''
    || $pwd === false || $pwd === '') {
    fwrite(STDERR, "Set SQL_SERVER_NAME, SQL_DATABASE, SQL_UID, and SQL_PWD." . PHP_EOL);
    exit(1);
}

$database = '{' . str_replace('}', '}}', $database) . '}';
$uid = '{' . str_replace('}', '}}', $uid) . '}';
$pwd = '{' . str_replace('}', '}}', $pwd) . '}';

$connectionOptions = [
    "Database" => $database,
    "UID" => $uid,
    "PWD" => $pwd,
    "Encrypt" => 1,
    "TrustServerCertificate" => 0,
];

$sqlsrvConnection = sqlsrv_connect($serverName, $connectionOptions);
if ($sqlsrvConnection === false) {
    foreach (sqlsrv_errors() as $error) {
        fwrite(
            STDERR,
            "SQLSRV {$error['SQLSTATE']} ({$error['code']}): {$error['message']}" . PHP_EOL
        );
    }
    exit(1);
}

$sqlsrvStatement = sqlsrv_query($sqlsrvConnection, "SELECT 1 AS TEST_VALUE");
if ($sqlsrvStatement === false) {
    foreach (sqlsrv_errors() as $error) {
        fwrite(
            STDERR,
            "SQLSRV {$error['SQLSTATE']} ({$error['code']}): {$error['message']}" . PHP_EOL
        );
    }
    sqlsrv_close($sqlsrvConnection);
    exit(1);
}

$sqlsrvRow = sqlsrv_fetch_array($sqlsrvStatement, SQLSRV_FETCH_ASSOC);
if ($sqlsrvRow === false || $sqlsrvRow === null || (int) $sqlsrvRow['TEST_VALUE'] !== 1) {
    fwrite(STDERR, "SQLSRV returned an unexpected result." . PHP_EOL);
    sqlsrv_free_stmt($sqlsrvStatement);
    sqlsrv_close($sqlsrvConnection);
    exit(1);
}

echo "SQLSRV query: 1" . PHP_EOL;
sqlsrv_free_stmt($sqlsrvStatement);
sqlsrv_close($sqlsrvConnection);

$failed = false;
try {
    $pdoConnection = new PDO(
        "sqlsrv:server=$serverName;Database=$database;Encrypt=1;TrustServerCertificate=0",
        $uid,
        $pwd,
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
    );
    $pdoStatement = $pdoConnection->query("SELECT 1 AS TEST_VALUE");
    $pdoRow = $pdoStatement->fetch(PDO::FETCH_ASSOC);
    if ($pdoRow === false || (int) $pdoRow['TEST_VALUE'] !== 1) {
        throw new RuntimeException("PDO_SQLSRV returned an unexpected result.");
    }

    echo "PDO_SQLSRV query: 1" . PHP_EOL;
} catch (Throwable $exception) {
    fwrite(STDERR, $exception->getMessage() . PHP_EOL);
    $failed = true;
} finally {
    unset($pdoStatement);
    unset($pdoConnection);
}

exit($failed ? 1 : 0);

Execute o programa antes da atualização e salve a saída bem-sucedida. Execute o arquivo inalterado novamente após reiniciar todos os processos do PHP:

php test-driver-upgrade.php

Ambas as execuções devem produzir:

SQLSRV query: 1
PDO_SQLSRV query: 1

Se a execução pós-atualização falhar, mantenha o SQLSTATE exato ou a exceção exata. Depois, compare a falha com a linha base, versões de extensão, configuração ativa, versão ODBC e status de reinicialização do processo. Reverta as duas extensões PHP juntas quando não puder corrigir o descompasso dentro da janela de deploy.

Após a verificação, exclua o arquivo de teste e limpe as variáveis de ambiente temporárias. No PowerShell, execute o seguinte:

Remove-Item .\verify-driver-upgrade.php, .\test-driver-upgrade.php
Remove-Item Env:\SQL_SERVER_NAME, Env:\SQL_DATABASE, Env:\SQL_UID, Env:\SQL_PWD

No Linux ou macOS, execute:

rm verify-driver-upgrade.php test-driver-upgrade.php
unset SQL_SERVER_NAME SQL_DATABASE SQL_UID SQL_PWD

Reverter uma atualização que não teve sucesso

  1. Pare os servidores web afetados, os pools do PHP-FPM e os workers de longa execução.

  2. Se você mudou a versão secundária do PHP, restaure o runtime anterior do PHP e aponte cada servidor web e worker de volta para essa instalação.

  3. Restaure os dois arquivos de drivers anteriores. Restaure as entradas anteriores do SQLSRV e PDO_SQLSRV de configuração juntos.

  4. Restaure o pacote ODBC anterior somente se a versão mais recente causou a falha e o pacote antigo continuar suportado pela versão do driver PHP que você restaurou.

  5. Reinicie os processos e execute novamente as verificações de versão básica e os testes de sanidade da aplicação.

  6. Mantenha os logs de atualização falhados e o erro exato de inicialização ou conexão do PHP. Eles ajudam a identificar se a falha pertence ao carregamento PHP, ao carregador do sistema operacional, ao ODBC ou à conexão com o banco de dados.

Solucionar problemas de atualização

Sintoma Causa provável Ação corretiva
O PIE tem sucesso, mas ExtensionVer permanece inalterado Uma entrada versionada antiga ainda carrega o arquivo anterior Substitua a entrada antiga, remova duplicatas e reinicie todos os processos PHP
SQLSRV e PDO_SQLSRV reportam versões diferentes Apenas uma extensão foi substituída ou uma SAPI tem configuração obsoleta Faça upgrade e configure ambas as extensões juntas em cada runtime
A CLI reporta a versão alvo, mas o site não A SAPI web usa outra instalação PHP ou não foi reiniciada Compare os diretórios de configuração e extensão, então reinicie o processo correto
A inicialização do PHP reporta um erro de arquitetura ou símbolo A extensão não corresponde à compilação do PHP Restaure os arquivos anteriores, depois reconstrua ou selecione os arquivos para a versão secundária correta do PHP, arquitetura e modo de segurança de threads
Extensões carregam, mas as conexões falham após uma alteração ODBC Configuração ODBC, comportamento de certificado, autenticação ou acesso à rede alterados Capture o estado SQLSTATE e o erro nativo antes de executar rollback ou mudar as configurações de conexão
Processos worker falham enquanto novas requisições web têm sucesso Workers de longa duração ainda mantêm a extensão ou configuração anterior Esvazie e reinicie todos os processos worker