アイドル状態の接続の回復性

PHP ドライバーのダウンロード

接続の回復性は、特定の制約内で、切断されたアイドル状態の接続を再確立できるという原則です。 データベースへの接続が失敗した場合、接続の回復性により、クライアントは自動的に再接続を試みます。 接続の回復性は、データ ソースのプロパティです。 SQL Server 2014 以降と Azure SQL Database のみが、接続の回復性をサポートしています。

接続の回復性は、接続文字列に追加できる ConnectRetryCountConnectRetryInterval の 2 つの接続キーワードを使用して実装されます。

Keyword Default 説明
ConnectRetryCount 0 から 255 までの整数 1 中止するまでに、切断された接続の再確立を試みる最大回数。 既定では、接続が切断されると、接続の再確立が 1 回試みられます。 値 0 は、再接続が試みられないことを意味します。
ConnectRetryInterval 1 から 60 までの整数 10 接続の再確立を試行する秒単位の時間間隔。 アプリケーションでは、接続途絶検出直後に再接続が試みられた後、ConnectRetryInterval 秒待ってから、再試行されます。 ConnectRetryCount が 0 の場合、このキーワードは無視されます。

ConnectRetryCountConnectRetryInterval を乗算した積が 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.

こちらもご覧ください

ODBC ドライバーの接続の回復性