Zaktualizuj sterowniki PHP dla SQL Server

Zaktualizuj SQLSRV i PDO_SQLSRV razem, aby oba rozszerzenia korzystały z tej samej rodziny wydań. Sterowniki PHP korzystają ze sterownika Microsoft ODBC dla SQL Server, więc przed aktualizacją sprawdź wymagania systemowe.

Aktualizacja zmienia natywny kod ładowany do procesów PHP. Mieszane wdrożenie może kontynuować uruchamianie poprzedniej wersji, ulec awarii podczas uruchamiania PHP lub udostępnić różne wersje sterowników dla CLI i aplikacji webowej. Zinwentaryzuj każde środowisko uruchomieniowe PHP i zachowaj poprzednie pliki oraz konfigurację do czasu zakończenia weryfikacji.

Wybierz ścieżkę ulepszenia

Bieżąca instalacja Instalacja docelowa Procedure
PIE PIE Uruchom PIE z tym samym plikiem wykonywalnym PHP lub parametrem explicit php-config, a następnie zweryfikuj każdy SAPI
Wydany ZIP dla Windows plik ZIP utworzony przez system Windows Zamień oba wersjonowane DLL i zaktualizuj oba wpisy konfiguracji razem
Plik ZIP wydany przez system Windows PIE Zainstaluj oba pakiety PIE, zamień wersjonowane wpisy DLL wpisami PIE i usuń duplikaty
Archiwum wydane dla systemu Linux lub macOS PIE Zainstaluj oba pakiety PIE, zamień wpisy „archive-filename” na sqlsrv.so i pdo_sqlsrv.so oraz zachowaj kolejność ładowania PDO
Linux lub macOS PIE Nowa podrzędna wersja PHP Zainstaluj nowe narzędzia programistyczne PHP, zbuduj oba rozszerzenia dla tej instalacji i skonfiguruj każdy interfejs SAPI osobno

Nie nadpisuj poprzednich plików binarnych, dopóki nie będziesz miał kopii umożliwiającej wycofanie zmian. Nie aktualizuj tylko jednego rozszerzenia, gdy aplikacja korzysta z obu API.

Przed uaktualnieniem

  1. Zanotuj plik wykonywalny PHP, plik konfiguracyjny, architekturę, tryb bezpieczeństwa wątków oraz aktualne wersje sterowników.

    php --version
    php --ini
    php --ri sqlsrv
    php --ri pdo_sqlsrv
    
  2. Zrób php.ini kopię zapasową pliku oraz wszystkich plików specyficznych .ini dla rozszerzenia, które ładują sqlsrv lub pdo_sqlsrv.

  3. Sprawdź tabelę zgodności dla docelowej wersji PHP i systemu operacyjnego.

  4. Sprawdź tabelę zgodności ODBC w wymaganiach systemowych. Zainstaluj obsługiwaną wersję ODBC przed lub podczas aktualizacji sterownika PHP, gdy docelowa wersja sterownika tego wymaga.

  5. Zaplanuj restart każdego procesu, który ładuje PHP, w tym serwera WWW, PHP FastCGI Process Manager (PHP-FPM), pracowników kolejek oraz długo działających pracowników linii poleceń.

  6. Zapisz punkt odniesienia z każdego środowiska uruchomieniowego:

    • ExtensionVer pokazane przez php --ri sqlsrv i php --ri pdo_sqlsrv.
    • Załadowano plik konfiguracyjny i zeskanowano katalog .ini.
    • Katalog rozszerzenia oraz nazwy plików aktywnego sterownika.
    • Test dymowy aplikacji zakończony powodzeniem, który wykorzystuje każde API, od których zależy aplikacja.
  7. Przygotuj wycofanie:

    • Zachowaj poprzednie środowisko uruchomieniowe PHP dostępne, jeśli zmienisz pomniejszą wersję PHP. Zarejestruj plik wykonywalny skonfigurowany dla każdego serwera WWW i procesu roboczego.
    • Zachowaj kopie poprzednich plików SQLSRV i PDO_SQLSRV.
    • Przechowuj kopie każdego zmienionego pliku php.ini lub pliku specyficznego dla rozszerzenia .ini.
    • Zanotuj poprzednią wersję pakietu ODBC, jeśli aktualizacja ją zmieni.
    • Określ, jak wstrzymać ruch lub pracę podczas wymiany natywnych plików rozszerzenia.

Uaktualnienie w systemie Windows z PIE

Użyj instalatora PHP Installer for Extensions (PIE) wraz z plikiem wykonywalnym PHP, który obsługuje aplikację. Najpierw pobierz i zweryfikowaj PIE. Przed uruchomieniem któregokolwiek z poleceń instalacyjnych przekieruj ruch aplikacji i zatrzymaj serwer WWW, procesy FastCGI oraz procesy robocze korzystające z tej instalacji PHP. Zapobiegaj ich automatycznemu restartowi, dopóki oba rozszerzenia oraz konfiguracja każdego z nich nie będą gotowe. Trzymaj osobną sesję wiersza poleceń dla PIE.

Tymczasowo skomentuj istniejące wpisy SQLSRV i PDO_SQLSRV w konfiguracji CLI używanej przez PIE. W przeciwnym razie proces PHP uruchamiający PIE może utrzymywać stare DLL załadowane i uniemożliwiać ich zastąpienie. Zachowaj włączone wymagane rozszerzenia PIE.

Z katalogu zawierającego pie.phar, zainstaluj oba pakiety osobno:

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

PIE instaluje php_sqlsrv.dll i php_pdo_sqlsrv.dll. We wszystkich aktywnych konfiguracjach zastąp wersjonowane wpisy ZIP, takie jak extension=php_sqlsrv_85_ts_x64.dll i extension=php_pdo_sqlsrv_85_ts_x64.dll, następującymi:

extension=php_sqlsrv.dll
extension=php_pdo_sqlsrv.dll

Włącz oba wpisy i usuń zduplikowane wpisy SQLSRV i PDO_SQLSRV, nawet jeśli PIE raportuje, że automatyczne włączenie się powiodło. Jeśli serwer WWW używa innej instalacji PHP, powtórz aktualizację oraz zmiany konfiguracji dla tej instalacji.

Restartuj każdy proces PHP, potem uruchom php --ri sqlsrv i php --ri pdo_sqlsrv, używając odpowiedniego pliku wykonywalnego. Potwierdź, że ExtensionVer raportuje docelową wersję dla obu sterowników. W przypadku aplikacji webowej ogranicz dostęp do strony diagnostycznej przed utworzeniem tymczasowej phpinfo() strony. Zweryfikuj obie wartości, a następnie usuń stronę.

Uaktualnienie instalacji ZIP w systemie Windows

  1. Pobierz archiwum ZIP dla Windows dla docelowej wersji ze strony Microsoft Drivers for PHP for SQL Server releases.

  2. Potwierdź, że nowe nazwy bibliotek dołączanych dynamicznie (DLL) odpowiadają pomocniczej wersji PHP, architekturze oraz trybowi bezpieczeństwa wątków. Zatrzymaj serwer WWW PHP lub procesy workera przed wymianą plików.

  3. Zastąp oba pliki php_sqlsrv_*.dll i php_pdo_sqlsrv_*.dll w katalogu rozszerzeń PHP. Zachowaj istniejące extension= wpisy, jeśli nazwy plików nadal się zgadzają. W przeciwnym razie aktualizuj je razem.

  4. Zainstaluj lub zaktualizuj sterownik Microsoft ODBC dla SQL Server, jeśli docelowy sterownik PHP wymaga nowszej obsługiwanej wersji.

  5. Restartuj każdy proces PHP, który korzysta z zastąpionych plików DLL. Działający proces utrzymuje stare natywne rozszerzenie załadowane aż do jego zakończenia.

Uaktualnianie na Linuksie lub macOS z PIE

  1. Jeśli PIE nie jest zainstalowane, postępuj zgodnie z konfiguracją PIE i wymaganiami wstępnymi platformy. Potwierdź, że narzędzia do programowania PHP oraz pakiet programistyczny ODBC są zainstalowane. W interaktywnej sesji PIE może poprosić o instalację brakujących narzędzi do budowania za pomocą menedżera pakietów platformy. W sesji nieinteraktywnej zainstaluj je przed uruchomieniem PIE.

  2. Wybierz instalację PHP przed aktualizacją. W przypadku instalacji z określoną wersją dodaj opcję PIE --with-php-config do obu poleceń instalacji. Na przykład używaj pie install --with-php-config=/usr/bin/php-config8.4 microsoft/sqlsrv, gdy zamierzonym narzędziem konfiguracyjnym jest /usr/bin/php-config8.4. Zastosuj tę samą opcję do microsoft/pdo_sqlsrv. W przypadku wersjonowanych plików wykonywalnych Alpine użyj poleceń instalacyjnych Alpine.

  3. Wyłącz ruch aplikacji i zatrzymaj serwer WWW, procesy PHP-FPM i procesy robocze korzystające z tej instalacji PHP. Zapobiegaj ich automatycznemu restartowi, dopóki rozszerzenia i ich konfiguracja nie będą gotowe. Trzymaj osobną sesję wiersza poleceń dla PIE.

    Tymczasowo skomentuj istniejące wpisy SQLSRV i PDO_SQLSRV w konfiguracji CLI używanej przez PIE. Pozostaw włączone wymagane rozszerzenia PIE.

  4. Ulepsz oba pakiety osobno. Te polecenia wykorzystują domyślną instalację PHP PIE:

    pie install microsoft/sqlsrv
    pie install microsoft/pdo_sqlsrv
    
  5. Sprawdź każdą aktywną konfigurację instalacji PHP używanej przez twoją aplikację. Jeśli poprzednia ręczna instalacja używa nazw plików archiwalnych, takich jak extension=SQLSRV_8.4_NTS.so i extension=PDO_SQLSRV_8.4_NTS.so, zastąp te wpisy nazwami plików zainstalowanymi przez PIE:

    extension=sqlsrv.so
    extension=pdo_sqlsrv.so
    

    Ponownie włącz oba wpisy sterowników i usuń duplikaty. Trzymaj PDO_SQLSRV w zeskanowanym pliku konfiguracyjnym, który ładuje się po PDO, jak opisano w Ładowanie sterowników w systemach Linux i macOS. Powtórz tę zmianę konfiguracji dla linii poleceń, PHP-FPM, serwera WWW oraz konfiguracji workerów, których używa Twoja aplikacja.

  6. Aktualizuj sterownik Microsoft ODBC dla SQL Server, gdy będzie to wymagane przez docelową wersję.

  7. Uruchom ponownie każdy proces roboczy CLI, proces roboczy kolejki, serwer WWW oraz usługę PHP-FPM korzystające z zaktualizowanej instalacji PHP.

Uruchom ponownie i zweryfikuj

Wymiana pliku rozszerzenia nie aktualizuje procesu PHP, który już załadował stary moduł binarny. Przed weryfikacją aktualizacji zrestartuj serwer WWW, PHP-FPM i wszystkie długotrwale działające workery PHP.

  1. Sprawdź środowisko uruchomieniowe wiersza poleceń:

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

    Na Linuksie lub macOS zastąp ostatnie polecenie na php -m | grep -E 'sqlsrv|pdo_sqlsrv'.

  2. W przypadku aplikacji webowej ogranicz dostęp do strony diagnostycznej przed utworzeniem tymczasowej phpinfo() strony. Zweryfikuj załadowany plik konfiguracyjny, katalog rozszerzenia oraz ExtensionVer dla obu sterowników. Potwierdź, że ExtensionVer pokazuje docelową wersję, a następnie usuń stronę.

  3. Uruchom istniejący test dymowy aplikacji, który sprawdzi zarówno SQLSRV, jak i PDO_SQLSRV, jeśli Twoja aplikacja korzysta z obu. Zachowaj niezmienioną konfigurację połączenia podczas tej kontroli, aby test aktualizacji nie sprawdzał także niepowiązanej zmiany połączenia.

Jeśli sterownik nie załaduje się, porównaj wersję PHP minor, architekturę, tryb bezpieczeństwa wątków, katalog rozszerzenia oraz instalację ODBC z wartościami zapisanymi przed aktualizacją.

Zweryfikuj zarówno API, jak i wersje

Zapisz ten program jako 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);

Uruchom program za pomocą programu wykonywalnego CLI i tymczasowo w każdym środowisku uruchomieniowym sieci. Sprawdź, czy obie zgłoszone wersje odpowiadają wersji zainstalowanej przez Ciebie. Usuń kopię z sieci po weryfikacji.

Program ten weryfikuje warstwę rozszerzenia PHP. Następnie przeprowadź test dymowy niezmienionej aplikacji, aby zweryfikować ładowanie ODBC, opcje połączenia, uwierzytelnianie, dostęp do bazy danych, zwrócone typy PHP oraz zachowanie czyszczenia.

Zweryfikuj zachowanie bazy danych przed i po aktualizacji

Używaj tego samego programu i ustawień połączenia przed i po aktualizacji. Pozostawienie testu bez zmian oddziela zmiany sterowników od zmian w aplikacji lub konfiguracji połączenia.

Ustaw zmienne środowiskowe SQL_SERVER_NAME, SQL_DATABASE, SQL_UID oraz SQL_PWD dla konta testowego, odpowiadając na monity. Wprowadź surowe wartości, bez cudzysłowów powłoki czy kodowania sterowników. Nie dodawaj danych uwierzytelniających w wierszu poleceń ani w nagranej sesji terminala.

W Windows PowerShell wpisz nazwę serwera i nazwę bazy danych, a następnie użyj okna uwierzytelniania lub monitu poświadczeń dla konta testowego:

$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

W systemie Linux lub macOS używaj powłoki Bash. Wyłącz śledzenie poleceń przed odczytem jakichkolwiek wartości. Monit hasła nie wyświetla wpisywanych znaków:

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

Środowisko zawiera hasło w tekstie jawnym, aby PHP mógł je odczytać. Używaj tych zmiennych tylko podczas sesji testowej, nie drukuj ich i usuwaj po testach.

Zapisz ten program jako test-driver-upgrade.php. Zachowaj wartości środowiska bez zmian. Program podwaja zamykające się klamry i dodaje zewnętrzne klamry przed przekazaniem nazwy bazy danych, nazwy użytkownika i hasła do sterownika. To kodowanie zachowuje dosłowne nawiasy klamrowe i zapobiega rozdzielaniu opcji połączeń przez średniki.

<?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);

Uruchom program przed aktualizacją i zapisz pomyślny wynik działania. Uruchom niezmieniony plik ponownie po ponownym uruchomieniu wszystkich procesów PHP:

php test-driver-upgrade.php

Oba przebiegi powinny dać:

SQLSRV query: 1
PDO_SQLSRV query: 1

Jeśli uruchomienie po aktualizacji nie powiodnie, zachowaj dokładny SQLSTATE lub wyjątek. Następnie porównaj błąd z bazową konfiguracją, wersjami rozszerzenia, aktywną konfiguracją, wersją ODBC oraz statusem restartu procesu. Cofnij oba rozszerzenia PHP razem, gdy nie możesz poprawić rozbieżności w ramach okna wdrożenia.

Po weryfikacji usuń plik testowy i usuń tymczasowe zmienne środowiskowe. W programie PowerShell uruchom:

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

W systemie Linux lub macOS uruchom polecenie:

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

Cofnij nieudane ulepszenie

  1. Zatrzymaj dotknięte serwery WWW, pule PHP-FPM i długo działające procesy robocze.

  2. Jeśli zmieniłeś wersję minor PHP, przywróć poprzednie środowisko uruchomieniowe PHP i wskaż każdy serwer WWW i proces roboczy ponownie na tę instalację.

  3. Przywróć oba poprzednie pliki sterownika. Przywróć poprzednie wpisy SQLSRV i PDO_SQLSRV konfiguracji razem.

  4. Przywracaj poprzedni pakiet ODBC tylko wtedy, gdy nowsza wersja spowodowała awarię, a starszy pakiet jest nadal obsługiwany przez wersję sterownika PHP, którą przywrócono.

  5. Zrestartuj procesy i ponownie przeprowadź kontrole wersji bazowej oraz testy dymne aplikacji.

  6. Zachowaj logi nieudanych aktualizacji oraz dokładne błędy uruchamiania lub połączenia w PHP. Pomagają one zidentyfikować, czy awaria dotyczy ładowania PHP, loadera systemu operacyjnego, ODBC lub połączenia bazy danych.

Rozwiązywanie problemów z uaktualnieniem

Objaw Prawdopodobna przyczyna Akcja naprawcza
PIE odnosi sukces, ale ExtensionVer pozostaje niezmienione Stary wpis wersjonowany nadal ładuje poprzedni plik Zamień stary wpis, usuń duplikaty i zrestartuj wszystkie procesy PHP
SQLSRV i PDO_SQLSRV raportują różne wersje Wymieniono tylko jedno rozszerzenie lub jeden SAPI ma nieaktualną konfigurację Aktualizuj i konfiguruj oba rozszerzenia jednocześnie w każdym środowisku uruchomieniowym
CLI raportuje wersję docelową, ale strona nie Web SAPI używa innej instalacji PHP lub nie zostało zrestartowane Porównaj katalogi konfiguracji i rozszerzeń, a następnie zrestartuj właściwy proces
Uruchamianie PHP zgłasza błąd architektury lub symbolu Rozszerzenie nie pasuje do kompilacji PHP Przywróć poprzednie pliki, a następnie odbuduj lub wybierz pliki dla odpowiedniej pomocniczej wersji PHP, architektury i trybu bezpieczeństwa wątków
Rozszerzenia się ładują, ale połączenia zawodzą po zmianie ODBC Zmieniona konfiguracja ODBC, zachowanie certyfikatów, uwierzytelnianie lub dostęp do sieci Uchwyć błąd SQLSTATE i natywny błąd przed cofnięciem lub zmianą ustawień połączenia
Procesy worker ulegają awarii, podczas gdy nowe żądania WWW są obsługiwane poprawnie Długotrwale działające procesy robocze nadal posiadają poprzednie rozszerzenie lub konfigurację Opróżnij i uruchom ponownie każdy proces roboczy