Atualizar 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, por isso verifique os requisitos do sistema antes de atualizar.

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

Escolha o caminho de atualização

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 todos os SAPI
ZIP gerado pelo Windows Windows extraiu o ZIP Substituir ambas as DLLs versionadas e atualizar ambas as entradas de configuração em conjunto
ZIP extraído do Windows PIE Instalar ambos os pacotes PIE, substituir entradas DLL versionadas por entradas PIE e remover duplicados
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 Instala as novas ferramentas de desenvolvimento PHP, constrói ambas as extensões para essa instalação PHP e configura cada SAPI separadamente

Não sobrescrevas os binários anteriores até teres uma cópia de rollback. Não atualize apenas uma extensão quando a aplicação usa ambas as APIs.

Antes de atualizar

  1. Registar o executável PHP, ficheiro 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 ficheiro e de quaisquer ficheiros específicos .ini de extensão que carreguem sqlsrv ou pdo_sqlsrv.

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

  4. Consulte 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 do driver de destino o exigir.

  5. Planeie um reinício de todos os processos que carreguem PHP, incluindo o servidor web, PHP FastCGI Process Manager (PHP-FPM), processos de fila e processos em linha de comandos de longa duração.

  6. Regista uma linha de base de cada runtime:

    • O ExtensionVer apresentado por php --ri sqlsrv e php --ri pdo_sqlsrv.
    • Carregou o ficheiro de configuração e analisou o diretório .ini.
    • O diretório de extensões e os nomes dos ficheiros dos drivers ativos.
    • Um teste smoke de aplicação que passa e que utiliza cada API da qual a sua aplicação depende.
  7. Prepare uma reversão:

    • Mantém o runtime PHP anterior disponível se mudares a versão secundária do PHP. Registar o executável configurado para cada servidor web e worker.
    • Guarde cópias dos ficheiros SQLSRV e PDO_SQLSRV anteriores.
    • Guarde cópias de cada ficheiro alterado php.ini ou ficheiro específico da extensão .ini.
    • Grava a versão anterior do pacote ODBC se a atualização a alterar.
    • Defina como parar o tráfego ou os processos worker enquanto os ficheiros de extensão nativos são substituídos.

Atualizar para uma versão superior no Windows com PIE

Use o PHP Installer for Extensions (PIE) com o executável PHP que executa a aplicação. Primeiro, descarregue 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 FastCGI e os workers que utilizam esta instalação de PHP. Impeça que reiniciem automaticamente até que ambas as extensões e a sua configuração estejam prontas. Mantém uma sessão de linha de comandos separada para o PIE.

Desative comentando temporariamente as entradas de extensão SQLSRV e PDO_SQLSRV existentes na configuração CLI usada pelo PIE. Caso contrário, o processo PHP que executa o 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 todas as configurações ativas, 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 reporte que a habilitação automática foi bem-sucedida. Se o servidor web usar uma instalação PHP diferente, repita as alterações de atualização e configuração dessa instalação.

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

Atualizar uma instalação do Windows ZIP

  1. Descarregue o Windows ZIP da versão pretendida na página de lançamentos Microsoft Drivers for PHP for SQL Server.

  2. Confirme que os nomes das novas bibliotecas de ligação dinâmica (DLL) correspondem à versão menor do PHP, à arquitetura e ao modo de segurança de execução. Pare o servidor web PHP ou os processos de trabalho antes de substituir ficheiros.

  3. Substitua ambos os ficheiros php_sqlsrv_*.dll e php_pdo_sqlsrv_*.dll no diretório de extensões PHP. Mantém as entradas existentes extension= se os nomes dos ficheiros continuarem a coincidir. Caso contrário, atualize-os em conjunto.

  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 utilizem as DLLs substituídas. Um processo em execução mantém a antiga extensão nativa carregada até sair.

Atualização no Linux ou macOS com PIE

  1. Siga os pré-requisitos de configuração e plataforma do PIE se o PIE não estiver instalado. Confirme que as ferramentas de desenvolvimento PHP e o pacote de desenvolvimento ODBC estão instalados. Numa sessão interativa, o PIE pode pedir para instalar ferramentas de compilação em falta através do gestor de pacotes da plataforma. Numa sessão não interativa, instale-os antes de executar o PIE.

  2. Selecione a instalação 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, utilize os comandos de instalação do Alpine.

  3. Drenar o tráfego da aplicação e parar o servidor web, os processos PHP-FPM e os workers que utilizam esta instalação PHP. Impeça que reiniciem automaticamente até que ambas as extensões e a sua configuração estejam prontas. Mantém uma sessão de linha de comandos 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. Atualiza ambos os pacotes separadamente. Estes comandos utilizam a instalação PHP padrão 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 ficheiros de arquivo como extension=SQLSRV_8.4_NTS.so e extension=PDO_SQLSRV_8.4_NTS.so, substitua essas entradas pelos nomes de ficheiros instalados no PIE:

    extension=sqlsrv.so
    extension=pdo_sqlsrv.so
    

    Volte a ativar ambas as entradas do driver e remova os duplicados. Manté PDO_SQLSRV num ficheiro de configuração analisado que carrega após o PDO, conforme descrito em Carregar os drivers no Linux e macOS. Repita esta alteração de configuração para a linha de comandos, PHP-FPM, servidor web e configurações de workers que a 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 da fila, servidor web e serviço PHP-FPM que utilize a instalação atualizada do PHP.

Reiniciar e verificar

Substituir um ficheiro 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 da linha de comandos:

    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, restringa o acesso a páginas de diagnóstico antes de criar uma página phpinfo() temporária. Verifique o ficheiro de configuração carregado, o diretório de extensões e ExtensionVer para ambos os drivers. Confirme que ExtensionVer reporta a versão alvo e depois remova a página.

  3. Executa um teste de fumo da aplicação existente que exerça tanto SQLSRV como PDO_SQLSRV se a tua aplicação usar ambos. Mantenha a configuração da ligação inalterada durante esta verificação para que um teste de atualização não teste também uma alteração de ligação não relacionada.

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

Verifique tanto as APIs como as versões

Guarde 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. Confirma se ambas as versões reportadas correspondem à versão que instalaste. Remova a cópia web após a verificação.

Este programa verifica a camada de extensão PHP. Execute o teste de fumo da aplicação inalterado depois para verificar o carregamento ODBC, opções de ligação, autenticação, acesso à base de dados, tipos PHP devolvidos e comportamento de limpeza.

Verificar o comportamento da base de dados antes e depois da atualização

Utilize o mesmo programa e definições de ligação antes e depois da atualização. Manter o teste inalterado separa as alterações do driver das alterações na aplicação ou na configuração da ligação.

Defina as SQL_SERVER_NAMEvariáveis , SQL_DATABASE, SQL_UID, e SQL_PWD de ambiente para uma conta de teste respondendo a prompts. Introduza os valores brutos, sem aspas de shell ou codificação do driver. Não inclua credenciais numa linha de comandos ou numa sessão de terminal gravada.

No PowerShell do Windows, introduza o nome do servidor e o nome da base de dados, depois utilize o diálogo de credencial 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, usa o Bash. Desative o rastreamento de comandos antes de ler qualquer valor. A solicitação de palavra-passe não mostra o que escreves:

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 palavra-passe em texto simples para que o PHP a possa ler. Use estas variáveis apenas na sessão de teste, não as imprima e limpe-as depois do teste.

Guarde este programa como test-driver-upgrade.php. Mantenha os valores do ambiente inalterados. O programa duplica as chaves de fecho e adiciona as chaves exteriores antes de passar o nome da base de dados, nome de utilizador e palavra-passe ao driver. Esta codificação preserva as chavetas literais e impede que os pontos e vírgulas separem as opções de ligaçã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);

Executa o programa antes da atualização e guarda o resultado gerado com êxito. Execute novamente o ficheiro inalterado depois de reiniciar todos os processos 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 exatamente o SQLSTATE ou exceção. Depois compare a falha com a baseline, versões de extensão, configuração ativa, versão ODBC e estado de reinício do processo. Reverte ambas as extensões PHP em conjunto quando não conseguires corrigir a incompatibilidade dentro da janela de implementação.

Após a verificação, apague o ficheiro de teste e limpe as variáveis temporárias do ambiente. 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 falhada

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

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

  3. Restaura ambos os ficheiros de drivers anteriores. Restaurar as entradas anteriores do SQLSRV e PDO_SQLSRV de configuração em conjunto.

  4. Restaure o pacote ODBC anterior apenas se a versão mais recente causou a falha e o pacote antigo continuar a ser suportado pela versão do controlador PHP restaurada.

  5. Reinicie os processos e execute novamente as verificações da versão base e os testes preliminares da aplicação.

  6. Guarda os registos de atualização falhados e o erro exato de arranque ou ligação do PHP. Ajudam a identificar se a falha pertence ao carregamento PHP, ao carregador do sistema operativo, ao ODBC ou à ligação à base de dados.

Solucionar problemas de uma atualização

Symptom Causa provável Ação corretiva
O PIE é bem-sucedido, mas ExtensionVer mantém-se inalterado Uma entrada versionada antiga ainda carrega o ficheiro anterior Substituir a entrada antiga, remover duplicados e reiniciar todos os processos PHP
SQLSRV e PDO_SQLSRV reportam versões diferentes Apenas uma extensão foi substituída ou uma SAPI tem uma configuração obsoleta Atualize e configure ambas as extensões em simultâneo em cada ambiente de execução
A CLI indica a versão de destino, mas o site não A SAPI web usa outra instalação PHP ou não foi reiniciada Compare diretórios de configuração e extensões, depois reinicie o processo correto
O arranque do PHP reporta um erro de arquitetura ou símbolo A extensão não corresponde à compilação do PHP Restaure os ficheiros anteriores, depois reconstrua ou selecione os ficheiros para a versão secundária do PHP correta, 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 do certificado, autenticação ou acesso à rede alterados Capturar o SQLSTATE e o erro nativo antes de efetuar rollback ou alterar as definições de ligação
Os processos em segundo plano falham enquanto novos pedidos web têm sucesso Workers de longa execução ainda mantêm a extensão ou configuração anterior Esvazie e reinicie todos os processos worker