SQLSRVとPDO_SQLSRVを同時にアップグレードし、両方の拡張機能が同じリリースファミリーを使うようにしましょう。 PHPドライバーはMicrosoft ODBCドライバーfor SQL Serverを使用しているため、アップグレード前にシステム要件を確認してください。
アップグレードはPHPプロセスに読み込まれるネイティブコードを変更します。 混合デプロイメントは前バージョンを継続して実行したり、PHP起動時に失敗したり、CLIやウェブアプリケーションで異なるドライババージョンが使われたりします。 すべてのPHPランタイムを一覧化し、検証が完了するまで以前のファイルや設定を保持してください。
アップグレードパスを選びます
| 現在のインストール | 対象のインストール | Procedure |
|---|---|---|
| パイ | パイ | 同じPHP実行ファイルまたは明示的な php-configでPIEを実行し、すべてのSAPIを確認してください |
| Windowsで作成されたZIP | Windows で作成された ZIP | 両方のバージョン付きDLLを置き換え、両方の構成エントリを同時に更新します |
| Windows で作成された ZIP | パイ | 両方のPIEパッケージをインストールし、バージョン付きDLLエントリをPIEエントリに置き換え、重複を削除します |
| LinuxまたはmacOS向けのリリース済みアーカイブ | パイ | 両方のPIEパッケージをインストールし、アーカイブファイル名エントリを sqlsrv.so と pdo_sqlsrv.soに置き換え、PDOロード順序を保持します |
| LinuxまたはmacOS PIE | 新しいPHPマイナーバージョン | 新しいPHP開発ツールをインストールし、そのPHPインストール用に両方の拡張機能をビルドし、それぞれのSAPIを個別に設定します |
ロールバックコピーができるまでは前のバイナリを上書きしないでください。 アプリケーションが両方のAPIを使う場合、1つの拡張機能だけをアップグレードしないでください。
アップグレードする前に
PHP実行ファイル、設定ファイル、アーキテクチャ、スレッドセーフティモード、現在のドライバーバージョンを記録します。
php --version php --ini php --ri sqlsrv php --ri pdo_sqlsrvphp.iniファイルと、pdo_sqlsrvまたは.iniを読み込む拡張子固有のsqlsrvファイルをバックアップしてください。ターゲットとなるPHPバージョンとOSのサポート マトリックス を確認してください。
システム要件のODBC互換性表を確認してください。 ターゲットドライバーのリリースで必要な場合は、PHPドライバーのアップグレード前またはアップグレード中にサポートされているODBCバージョンをインストールしてください。
PHPを読み込むすべてのプロセスの再起動を予定してください。ウェブサーバー、PHP FastCGIプロセスマネージャー(PHP-FPM)、キューワーカー、長期間実行されているコマンドラインワーカーを含みます。
各ランタイムのベースラインを記録する:
-
php --ri pdo_sqlsrvとExtensionVerによって示されるphp --ri sqlsrv。 - 読み込まれた設定ファイルとスキャンされた
.iniディレクトリ - 拡張機能ディレクトリとアクティブドライバーのファイル名です。
- アプリケーションが依存する各APIを使った、成功するアプリケーションのスモークテストです。
-
ロールバックの準備:
- PHPのマイナーバージョンを変更する場合は、以前のPHPランタイムをそのまま利用可能にしてください。 各ウェブサーバーとワーカーごとに設定された実行ファイルを記録します。
- 以前のSQLSRVやPDO_SQLSRVファイルのコピーを保管してください。
- 変更された
php.iniや拡張機能固有の.iniファイルのコピーをすべて保管してください。 - アップグレードで変更された場合は、前のODBCパッケージのバージョンを記録してください。
- ネイティブの拡張ファイルを置き換える間にトラフィックやワーカーを停止する方法を定義してください。
WindowsでPIEを使用したアップグレード
アプリケーションを提供するPHP実行ファイルと組み合わせて、PHP Installer for Extensions(PIE)を使いましょう。 まず、 PIEをダウンロードして検証します。 いずれかのインストールコマンドを実行する前に、アプリケーションへのトラフィックを切り離し、このPHPインストールを使用するウェブサーバー、FastCGIプロセス、ワーカーを停止してください。 拡張機能と設定が揃うまで自動再起動を防いでください。 PIE用のコマンドラインセッションを別に用意してください。
PIEで使用されるCLI構成内の既存のSQLSRVおよびPDO_SQLSRV拡張エントリを一時的にコメントアウトします。 そうでなければ、PIEを実行しているPHPプロセスが古いDLLを読み込んだままにし、置き換えを妨げる可能性があります。 PIEの前提拡張は有効にしておきましょう。
pie.pharを含むディレクトリから、両方のパッケージを別々にインストールしてください:
php .\pie.phar install microsoft/sqlsrv
php .\pie.phar install microsoft/pdo_sqlsrv
PIEは php_sqlsrv.dll と php_pdo_sqlsrv.dllをインストールします。 すべてのアクティブな構成において、extension=php_sqlsrv_85_ts_x64.dll や extension=php_pdo_sqlsrv_85_ts_x64.dll などのバージョン付きZIPエントリを以下のように置き換えてください:
extension=php_sqlsrv.dll
extension=php_pdo_sqlsrv.dll
両方のエントリを有効にし、PIEが自動有効化が成功したと報告しても、重複するSQLSRVやPDO_SQLSRVエントリを削除してください。 もしウェブサーバーが別のPHPインストールを使っている場合は、そのインストールでアップグレードと設定の変更を繰り返し行ってください。
各PHPプロセスを再起動し、対応する実行ファイルで php --ri sqlsrv と php --ri pdo_sqlsrv を実行します。
ExtensionVer が両方のドライバーについてターゲットバージョンを報告していることを確認してください。 ウェブアプリケーションの場合、一時的なページを作成する前にphpinfo()してください。 両方の値を確認してからページを削除してください。
Windows ZIPインストールのアップグレード
ターゲットリリースのWindows ZIPは、Microsoft Drivers for PHP for SQL Serverのリリースページからダウンロードできます。
新しい動的リンクライブラリ(DLL)の名前がPHPのマイナーバージョン、アーキテクチャ、スレッドセーフティモードと一致しているか確認してください。 ファイルを置き換える前にPHPのウェブサーバーやワーカープロセスを停止してください。
PHP拡張ディレクトリ内の
php_sqlsrv_*.dllファイルとphp_pdo_sqlsrv_*.dllファイルの両方を置き換えてください。 ファイル名が一致しているなら、既存のextension=エントリをそのまま残してください。 それ以外の場合は、まとめて更新してください。ターゲットとなるPHPドライバーが新しい対応バージョンを必要とする場合は、SQL Server Microsoft ODBCドライバーをインストールしたりアップグレードしたりしてください。
置き換えたDLLを使うすべてのPHPプロセスを再起動してください。 実行中のプロセスは、終了するまで古いネイティブ拡張を読み込みたままにします。
LinuxやmacOSでPIE を使用してアップグレードしてください
PIEがインストールされていない場合は、PIEの設定とプラットフォームの前提条件を参照してください。 PHP開発ツールとODBC開発パッケージがインストールされているか確認してください。 インタラクティブセッションでは、PIEはプラットフォームパッケージマネージャーを通じて不足しているビルドツールのインストールを促すことができます。 非インタラクティブなセッションでは、PIEを実行する前にそれらをインストールしてください。
アップグレード前に対象のPHPを選択してください。 バージョン付きインストールの場合は、両方のインストールコマンドにPIEの
--with-php-configオプションを追加してください。 例えば、意図された設定ツールがpie install --with-php-config=/usr/bin/php-config8.4 microsoft/sqlsrvである場合は、/usr/bin/php-config8.4を使います。 同じオプションをmicrosoft/pdo_sqlsrvにも適用してください。 Alpineのバージョン対応実行ファイルについては、 Alpineのインストールコマンドを使ってください。アプリケーションのトラフィックを切り離し、このPHPインストールを利用するウェブサーバー、PHP-FPM プロセス、ワーカーを停止します。 拡張機能と設定が揃うまで自動再起動を防いでください。 PIE用のコマンドラインセッションを別に用意してください。
PIEで使用されるCLI構成内の既存のSQLSRVおよびPDO_SQLSRV拡張エントリを一時的にコメントアウトします。 PIEの前提となる拡張機能は有効にしておきましょう。
両方のパッケージを別々にアップグレードしてください。 これらのコマンドはPIEのデフォルトのPHPインストールを使用しています:
pie install microsoft/sqlsrv pie install microsoft/pdo_sqlsrvアプリケーションで使われているPHPインストールのアクティブな設定をすべて確認してください。 以前の手動インストールで
extension=SQLSRV_8.4_NTS.soやextension=PDO_SQLSRV_8.4_NTS.soなどのアーカイブファイル名が使われている場合は、それらのエントリをPIEでインストールされたファイル名に置き換えてください。extension=sqlsrv.so extension=pdo_sqlsrv.so両方のドライバーエントリを再有効にし、重複するものを削除してください。 PDO_SQLSRVは、Linux と macOS でドライバーを読み込むで説明されているように、PDOの後に読み込まれるスキャン済みの構成ファイルに保持してください。 この設定変更を、アプリケーションが使用するコマンドライン、PHP-FPM、ウェブサーバー、ワーカーの構成にも適用します。
ターゲット リリースで必要な場合は、SQL Server 用 Microsoft ODBC ドライバーをアップグレードしてください。
アップグレードされたPHPインストールを使用しているCLIワーカー、キューワーカー、ウェブサーバー、PHP-FPM サービスを再起動してください。
再起動して確認
拡張モジュールのファイルを置き換えても、すでに古いバイナリを読み込んだPHPプロセスが更新されることはありません。 アップグレードを検証する前に、ウェブサーバー、PHP-FPM、そして長期間稼働しているPHPワーカーを再起動してください。
コマンドラインのランタイムを確認してください:
php --ri sqlsrv php --ri pdo_sqlsrv php -m | findstr /I "sqlsrv pdo_sqlsrv"LinuxやmacOSでは、最後のコマンドを
php -m | grep -E 'sqlsrv|pdo_sqlsrv'に置き換えてください。ウェブアプリケーションの場合、一時的なページを作成する前に
phpinfo()してください。 両方のドライバーで読み込まれた設定ファイル、拡張機能ディレクトリ、ExtensionVerを確認してください。ExtensionVerがターゲットバージョンを報告しているか確認し、その後ページを削除してください。アプリケーションが両方を使用している場合は、SQLSRV と PDO_SQLSRV の両方を検証する既存のアプリケーション スモーク テストを実行してください。 このチェック中は接続設定を変更しないようにしてください。アップグレードテストで無関係な接続変更もテストされないようにするためです。
ドライバがロードできなかった場合は、PHPのマイナーバージョン、アーキテクチャ、スレッドセーフティモード、拡張ディレクトリ、ODBCインストールをアップグレード前に記録した値と比較してください。
APIとバージョンの両方を検証してください
このプログラムを 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);
CLI実行ファイルでプログラムを実行し、一時的に各ウェブランタイム経由で実行します。 報告された両方のバージョンが、あなたがインストールしたリリースと一致しているか確認してください。 確認後にウェブコピーを削除してください。
このプログラムはPHP拡張層を検証します。 変更されていないアプリケーションのスモークテストを実行し、ODBCの読み込み、接続オプション、認証、データベースアクセス、返されたPHP型、クリーンアップの動作を確認します。
アップグレード前後のデータベースの挙動を確認してください
アップグレード前後で同じプログラムと接続設定を使いましょう。 テストを変更せずに保つことで、ドライバーの変更とアプリケーションや接続設定の変更を分けることができます。
プロンプトに答えて、テストアカウントの SQL_SERVER_NAME、SQL_DATABASE、SQL_UID、SQL_PWD の環境変数を設定しましょう。 シェルの引用符やドライバーのエンコーディングなしで生の値を入力します。 コマンドラインや録画されたターミナルセッションに認証情報を含めないでください。
Windows PowerShellでサーバー名とデータベース名を入力し、認証ダイアログまたはプロンプトを使用してテストアカウントの資格情報を入力します:
$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
LinuxやmacOSならBashを使いましょう。 値を読む前にコマンドトレーシングを無効にしてください。 パスワードのプロンプトでは入力内容は表示されません:
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
環境には平文パスワードが含まれているため、PHPはそれを読み取ることができます。 これらの変数はテストセッションでのみ使用し、印刷せず、テスト後にクリアしてください。
このプログラムを test-driver-upgrade.phpとして保存してください。 環境変数の値は変更しないでください。 プログラムは閉鎖ブレースを倍増させ、外側のブレースを追加してから、データベース名、ユーザー名、パスワードをドライバーに渡します。 このエンコーディングによりリテラルな波かっこが保持され、セミコロンで接続オプションを区切るのを防ぎます。
<?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);
アップグレード前にプログラムを実行し、正常終了時の出力を保存してください。 すべてのPHPプロセスを再起動した後、変更されていないファイルを再度実行してください:
php test-driver-upgrade.php
両ランとも以下の成果が出るはずです:
SQLSRV query: 1
PDO_SQLSRV query: 1
もしアップグレード後の実行が失敗した場合は、正確なSQLSTATEまたは例外を保持します。 次に、障害をベースライン、拡張バージョン、アクティブ設定、ODBCバージョン、プロセス再起動の状態と比較します。 展開ウィンドウ内で不一致が修正できない場合は、両方のPHP拡張を一緒にロールバックしてください。
検証後、テストファイルを削除し、一時的な環境変数をクリアしてください。 PowerShell で、以下を実行します。
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
Linux または macOS で、次を実行:
rm verify-driver-upgrade.php test-driver-upgrade.php
unset SQL_SERVER_NAME SQL_DATABASE SQL_UID SQL_PWD
失敗したアップグレードをロールバックする
影響を受けたウェブサーバー、PHP-FPM プール、長時間実行中のワーカーを停止させてください。
もしPHPのマイナーバージョンを変更した場合は、前のPHPランタイムを復元し、各ウェブサーバーとワーカーをそのインストールに戻してください。
両方の以前のドライバーファイルを復元してください。 前のSQLSRVとPDO_SQLSRV設定エントリを一緒に復元します。
新しいバージョンが障害の原因となっており、かつ復元したPHPドライババージョンが古いパッケージをサポートしている場合にのみ、以前のODBCパッケージを復元してください。
プロセスを再起動し、ベースラインのバージョンチェックとアプリケーションのスモークテストを再実行してください。
失敗したアップグレードログと、正確なPHPの起動エラーまたは接続エラーを保管してください。 これらは、障害がPHPの読み込み、オペレーティングシステムローダー、ODBC、またはデータベース接続のいずれかに起因しているかを特定するのに役立ちます。
アップグレードのトラブルシューティング
| 症状: | 考えられる原因 | 是正措置 |
|---|---|---|
PIEは成功していますが、ExtensionVerは変更されていません |
古いバージョン付きエントリは依然として前のファイルを読み込みます | 古いエントリを置き換え、重複を削除し、すべてのPHPプロセスを再起動してください |
| SQLSRVとPDO_SQLSRVは異なるバージョンを報告します | 1つの拡張機能だけが置き換えられた、あるいは1つのSAPIの構成が古くなっています | 両方の拡張機能を毎ランタイムで同時にアップグレード・設定してください |
| CLIはターゲットバージョンを報告しますが、ウェブサイトは報告していません | ウェブSAPIは別のPHPインストールを使っているか、再起動されていない可能性があります | 設定ディレクトリと拡張ディレクトリを比較し、正しいプロセスを再起動してください |
| PHP の起動時にアーキテクチャまたはシンボルのエラーが報告される | 拡張はPHPビルドと一致しません | 以前のファイルを復元し、その後正しいPHPマイナーバージョン、アーキテクチャ、スレッドセーフティモードに合わせてファイルを再構築または選択します |
| 拡張はロードされますが、ODBC変更後に接続が失敗します | ODBCの設定、証明書の挙動、認証、またはネットワークアクセスが変更されました | ロールバックや接続設定を変更する前に、SQLSTATEとネイティブエラーをキャプチャしてください |
| ワーカープロセスで障害が発生する一方で、新しいウェブリクエストは成功します | 長時間実行中のワーカーは、以前の拡張機能または設定を引き続き保持しています | すべてのワーカープロセスをドレインして再起動してください |