アイドル状態の接続の回復性
接続の回復性は、特定の制約内で、切断されたアイドル状態の接続を再確立できるという原則です。 データベースへの接続が失敗した場合、接続の回復性により、クライアントは自動的に再接続を試みます。 接続の回復性は、データ ソースのプロパティです。 SQL Server 2014 以降と Azure SQL Database のみが、接続の回復性をサポートしています。
接続の回復性は、接続文字列に追加できる ConnectRetryCount
と ConnectRetryInterval
の 2 つの接続キーワードを使用して実装されます。
Keyword | 値 | 既定 | 説明 |
---|---|---|---|
ConnectRetryCount |
0 から 255 までの整数 | 1 | 中止するまでに、切断された接続の再確立を試みる最大回数。 既定では、接続が切断されると、接続の再確立が 1 回試みられます。 値 0 は、再接続が試みられないことを意味します。 |
ConnectRetryInterval |
1 から 60 までの整数 | 10 | 接続の再確立を試行する秒単位の時間間隔。 アプリケーションでは、接続途絶検出直後に再接続が試みられた後、ConnectRetryInterval 秒待ってから、再試行されます。 ConnectRetryCount が 0 の場合、このキーワードは無視されます。 |
ConnectRetryCount
と ConnectRetryInterval
を乗算した積が LoginTimeout
より大きい場合、クライアントは LoginTimeout
に達した時点で接続の試行を一時停止します。それ以外の場合は、ConnectRetryCount
に達するまで再接続を試みます。
解説
接続の回復性は、接続がアイドル状態のときに適用されます。 たとえば、トランザクションの実行中にエラーが発生した場合は、再接続の試行はトリガーされません。他の場合と同様に失敗します。 復旧不可能なセッション状態と呼ばれる次の状況では、再接続の試行はトリガーされません。
- 一時テーブル
- グローバル カーソルとローカル カーソル
- トランザクション コンテキストとセッション レベルのトランザクション ロック
- アプリケーション ロック
- EXECUTE AS/REVERT セキュリティ コンテキスト
- OLE オートメーション ハンドル
- 準備済み XML ハンドル
- トレース フラグ
例
次のコードでは、データベースに接続してクエリが実行されます。 接続はセッションを強制終了することによって中断され、切断された接続を使用して新しいクエリが試行されます。 この例では、AdventureWorks サンプル データベースを使用します。
この例では、接続を切断する前にバッファー カーソルを指定します。 バッファー カーソルを指定しない場合、アクティブなサーバー側カーソルが存在するため、接続は再確立されません。 そのため、接続が壊れた場合に、アイドル状態になりません。 ただし、その場合でも、接続を断つ前に sqlsrv_free_stmt()
を呼び出してカーソルを解放すると、接続が正常に再確立されます。
<?php
// This function breaks the connection by determining its session ID and killing it.
// A separate connection is used to break the main connection because a session
// cannot kill itself. The sleep() function ensures enough time has passed for KILL
// to finish ending the session.
function BreakConnection( $conn, $conn_break )
{
$stmt1 = sqlsrv_query( $conn, "SELECT @@SPID" );
if ( sqlsrv_fetch( $stmt1 ) )
{
$spid=sqlsrv_get_field( $stmt1, 0 );
}
$stmt2 = sqlsrv_prepare( $conn_break, "KILL ".$spid );
sqlsrv_execute( $stmt2 );
sleep(1);
}
// Connect to the local server using Windows authentication and specify
// AdventureWorks as the database in use. Specify values for
// ConnectRetryCount and ConnectRetryInterval as well.
$databaseName = 'AdventureWorks2022';
$serverName = '(local)';
$connectionInfo = array( "Database"=>$databaseName, "ConnectRetryCount"=>10, "ConnectRetryInterval"=>10 );
$conn = sqlsrv_connect( $serverName, $connectionInfo );
if( $conn === false)
{
echo "Could not connect.\n";
die( print_r( sqlsrv_errors(), true));
}
// A separate connection that will be used to break the main connection $conn
$conn_break = sqlsrv_connect( $serverName, array( "Database"=>$databaseName) );
// Create a statement to retrieve the contents of a table
$stmt1 = sqlsrv_query( $conn, "SELECT * FROM HumanResources.Employee",
array(), array( "Scrollable"=>"buffered" ) );
if( $stmt1 === false )
{
echo "Error in statement 1.\n";
die( print_r( sqlsrv_errors(), true ));
}
else
{
echo "Statement 1 successful.\n";
$rowcount = sqlsrv_num_rows( $stmt1 );
echo $rowcount." rows in result set.\n";
}
// Now break the connection $conn
BreakConnection( $conn, $conn_break );
// Create another statement. The connection will be reestablished.
$stmt2 = sqlsrv_query( $conn, "SELECT * FROM HumanResources.Department",
array(), array( "Scrollable"=>"buffered" ) );
if( $stmt2 === false )
{
echo "Error in statement 2.\n";
die( print_r( sqlsrv_errors(), true ));
}
else
{
echo "Statement 2 successful.\n";
$rowcount = sqlsrv_num_rows( $stmt2 );
echo $rowcount." rows in result set.\n";
}
sqlsrv_close( $conn );
sqlsrv_close( $conn_break );
?>
予想される出力:
Statement 1 successful.
290 rows in result set.
Statement 2 successful.
16 rows in result set.