Устойчивость соединения в режиме ожидания
Устойчивость подключения является принципом, при котором разорванное подключение может быть восстановлено в пределах некоторых ограничений. В случае сбоя подключения к базе данных устойчивость подключения позволяет клиенту автоматически попытаться восстановить соединение. Устойчивость подключения является свойством источника данных. Устойчивость подключения поддерживается только в SQL Server 2014 и более поздних версиях, а также в Базе данных SQL Azure.
Устойчивость подключения реализуется с помощью двух ключевых слов подключения, которые можно добавить в строки подключения: ConnectRetryCount
и ConnectRetryInterval
.
Ключевое слово | Values | По умолчанию. | Description |
---|---|---|---|
ConnectRetryCount |
Целое число от 0 до 255 (включительно). | 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.