ODBC 驱动程序中的连接复原

下载 ODBC 驱动程序

为了确保应用程序能与 Azure SQL 数据库保持连接,ODBC 驱动程序可以还原空闲连接。

重要

Microsoft Azure SQL 数据库和 SQL Server 2014(及更高版本)服务器版本支持连接复原能力功能。

从 Microsoft ODBC Driver 11 for SQL Server 开始,Windows 上开始提供此功能。 从 Microsoft ODBC Driver 17 for SQL Server 版本 17.2 开始,Linux 上开始提供此功能。

有关空闲连接复原的详细信息,请参阅技术文章 - 空闲连接复原

为控制重新连接行为,ODBC Driver for 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 之间。 重新连接的总时间不能超过连接超时(SQLSetStmtAttr 中的 SQL_ATTR_QUERY_TIMEOUT)。 默认值为 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

在服务器上执行命令的任何函数都会返回以下状态代码:

状态 Message
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) 建立连接,该名称使用 Windows 上的 ODBC Driver for SQL Server。 DSN 使用 SQL Server 身份验证,并指定用户 ID。 然后,func1 使用 SQL_COPT_SS_CONNECT_RETRY_COUNT 来检索连接重试次数。

func2 使用 SQLDriverConnectConnectRetryCount 连接字符串关键字和连接属性,检索连接重试和重试间隔的设置。

// 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_for_userID;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();
}

另请参阅

Microsoft ODBC Driver for SQL Server