Устойчивость подключения в драйвере ODBC
Чтобы обеспечить подключение приложений, драйвер ODBC может восстановить неактивные подключения.
Внимание
Функция устойчивости подключений поддерживается в База данных SQL Microsoft Azure, базе данных SQL Fabric и версиях сервера SQL Server 2014 (и более поздних версий).
Эта функция доступна в Windows, начиная с Microsoft ODBC Driver 11 for SQL Server. Она доступна в Linux, начиная с версии 17.2 Microsoft ODBC Driver 17 for SQL Server.
Дополнительные сведения об устойчивости неактивных подключений см. в технической статье об устойчивости неактивных подключений.
Для управления поведением повторного подключения драйвер ODBC для SQL Server имеет два варианта:
Число попыток подключения.
Число попыток подключения управляет количеством повторных попыток подключения в случае сбоя соединения. Допустимы значения от 0 до 255. Ноль (0) означает отсутствие повторных попыток возобновления соединения. Значение по умолчанию — одна попытка повторного подключения.
Можно изменить число повторных попыток подключения, когда вы:
определяете или изменяете источник данных, использующий ODBC Driver for SQL Server с элементом управления Число попыток подключения;
Пользуйтесь ключевым словом строки подключения
ConnectRetryCount
.Чтобы извлечь количество повторных попыток подключения, используйте атрибут подключения
SQL_COPT_SS_CONNECT_RETRY_COUNT
(только для чтения). Если приложение подключается к серверу, который не поддерживает устойчивость подключений,SQL_COPT_SS_CONNECT_RETRY_COUNT
возвращает 0.
Интервал повтора подключения.
Интервал повтора подключения указывает количество секунд между попытками подключения. Допустимые значения: 1–60. Общее время для повторного подключения не может превышать время ожидания подключения (SQL_ATTR_QUERY_TIMEOUT в SQLSetStmtAttr). Значение по умолчанию — 10 секунд.
Можно изменить интервал повтора подключения, когда вы:
определяете или изменяете источник данных, использующий ODBC Driver for SQL Server с элементом управления Интервал повторных попыток подключения;
Пользуйтесь ключевым словом строки подключения
ConnectRetryInterval
.Чтобы извлечь продолжительность интервала повтора подключения, используйте атрибут подключения
SQL_COPT_SS_CONNECT_RETRY_INTERVAL
(только для чтения).
Если приложение устанавливает соединение с SQL_DRIVER_COMPLETE_REQUIRED, а затем пытается выполнить инструкцию через разорванное соединение, драйвер ODBC не отображает это диалоговое окно повторно. Кроме того, во время восстановления наблюдается следующее:
- Во время восстановления любой вызов метода
SQLGetConnectAttr(SQL_COPT_SS_CONNECTION_DEAD)
должен возвращатьSQL_CD_FALSE
. - Если восстановление завершается сбоем, любой вызов метода
SQLGetConnectAttr(SQL_COPT_SS_CONNECTION_DEAD)
должен возвращатьSQL_CD_TRUE
.
Любая функция, которая выполняет команду на сервере, возвращает следующие коды состояния:
Штат | Сообщение |
---|---|
IMC01 |
The connection is broken and recovery is not possible. The client driver attempted to recover the connection one or more times and all attempts failed. Increase the value of ConnectRetryCount to increase the number of recovery attempts. |
IMC02 |
The server did not acknowledge a recovery attempt, connection recovery is not possible. |
IMC03 |
The server did not preserve the exact client TDS version requested during a recovery attempt, connection recovery is not possible. |
IMC04 |
The server did not preserve the exact server major version requested during a recovery attempt, connection recovery is not possible. |
IMC05 |
The connection is broken and recovery is not possible. The connection is marked by the server as unrecoverable. No attempt was made to restore the connection. |
IMC06 |
The connection is broken and recovery is not possible. The connection is marked by the client driver as unrecoverable. No attempt was made to restore the connection. |
Пример
Следующий пример содержит две функции. func1
демонстрирует, как подключиться к имени источника данных (DSN), которое использует ODBC Driver for SQL Server в среде Windows. Имя DSN использует проверку подлинности SQL Server и задает идентификатор пользователя. Затем func1
извлекает число повторных попыток подключения с помощью SQL_COPT_SS_CONNECT_RETRY_COUNT
.
func2
использует SQLDriverConnect
, ключевое слово строки подключения ConnectRetryCount
и атрибуты подключения, чтобы получить параметр для повторных попыток подключения и интервала повторных попыток.
// Connection_resiliency.cpp
// compile with: odbc32.lib
#include <windows.h>
#include <stdio.h>
#include <sqlext.h>
#include <msodbcsql.h>
void func1() {
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
SQLRETURN retcode;
SQLSMALLINT i = 21;
// Allocate environment handle
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
// Set the ODBC version environment attribute
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
// Allocate connection handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
// Set login timeout to 5 seconds
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
// Connect to data source
retcode = SQLConnect(hdbc, (SQLCHAR*)"MyDSN", SQL_NTS, (SQLCHAR*)"userID", SQL_NTS, (SQLCHAR*)"password_for_userID", SQL_NTS);
retcode = SQLGetConnectAttr(hdbc, SQL_COPT_SS_CONNECT_RETRY_COUNT, &i, SQL_IS_INTEGER, NULL);
// Allocate statement handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
// Process data
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
}
SQLDisconnect(hdbc);
}
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
}
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
}
void func2() {
SQLHENV henv;
SQLHDBC hdbc1;
SQLHSTMT hstmt;
SQLRETURN retcode;
SQLSMALLINT i = 21;
#define MAXBUFLEN 255
SQLCHAR ConnStrIn[MAXBUFLEN] = "DRIVER={ODBC Driver 18 for SQL Server};SERVER=server_that_supports_connection_resiliency;Encrypt=yes;UID=userID;PWD=<password>;ConnectRetryCount=2";
SQLCHAR ConnStrOut[MAXBUFLEN];
SQLSMALLINT cbConnStrOut = 0;
// Allocate environment handle
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
// Set the ODBC version environment attribute
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3_80, SQL_IS_INTEGER);
// Allocate connection handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);
// Set login timeout to 5 seconds
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
// SQLSetConnectAttr(hdbc1, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retcode = SQLDriverConnect(hdbc1, NULL, ConnStrIn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
}
retcode = SQLGetConnectAttr(hdbc1, SQL_COPT_SS_CONNECT_RETRY_COUNT, &i, SQL_IS_INTEGER, NULL);
retcode = SQLGetConnectAttr(hdbc1, SQL_COPT_SS_CONNECT_RETRY_INTERVAL, &i, SQL_IS_INTEGER, NULL);
}
}
}
int main() {
func1();
func2();
}