1. 程式人生 > >OBDC:連線與連線池

OBDC:連線與連線池

在使用C++訪問資料庫時一定會使用到連線與連線池,下面就以MS SQL Server為例,介紹一下如何使用它們。

目錄

一、連線字串是怎樣定義的?

二、如何使用連線字串?

三、連線中需要設定哪些屬性?

四、如何獲取連線的屬性值?

五、如何設定連線池

六、如何從連線池中取出連線,如何釋放連線池中的連線?


一、連線字串是怎樣定義的?

下面通過一個例子,說明連線字串要如何配置:

Driver={ODBC Driver 17 for SQL Server};Address=tcp:127.0.0.1,1433;Server=\\TestServer;Database=testDB;Uid=guest;Pwd=12345678;language=Simplified Chinese;

  •  Driver——表示所使用的驅動名稱。本機可使用的驅動可以在“ODBC資料來源” - > “驅動程式”中找到所有可用驅動程式。如果不想自己手動輸入,也可以在“ODBC資料來源” - > “檔案DNS”點選“新增”,選中想要使用的驅動,點選“高階”,就可以看到可以複製的驅動名稱。
  • Address——表示要連線的資料庫網路地址。一般包格式:
     Address=[protocol:]Address[,port |\pipe\pipename]
     協議可以是 tcp (TCP/IP)、 lpc (共享記憶體)或 np (命名管道)
  • Server——表示資料庫例項名。一般包格式:
     Server=
    [protocol:]Server[,port]
     協議可以是 tcp (TCP/IP)、 lpc (共享記憶體)或 np (命名管道)
  • Database——表示資料庫名
  • Uid——表示登入使用者名稱
  • Pwd——表示登入使用者密碼
  • Language——表示資料庫伺服器使用的語言(可選)

 其中Address的內容可以和到Server中。

二、如何使用連線字串?

SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;

SQLRETURN retcode;

# 分配環境控制代碼
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
# 使用環境控制代碼設定驅動版本號
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
# 分配連線控制代碼
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
# 設定連線登入超時
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);

SQLWCHAR outstr[1024];
SQLSMALLINT outstrlen;
retcode = SQLDriverConnect(hdbc, NULL, (SQLWCHAR*)
L"Driver={ODBC Driver 17 for SQL Server};Server=127.0.0.1,1433\\TestServer;Database=testDB;Uid=sa;Pwd=12345678;", 
SQL_NTS, outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_NOPROMPT);

SQLDriverConnect函式的定義如下:

SQLRETURN SQLDriverConnect(  
     SQLHDBC         ConnectionHandle,  
     SQLHWND         WindowHandle,  
     SQLCHAR *       InConnectionString,  
     SQLSMALLINT     StringLength1,  
     SQLCHAR *       OutConnectionString,  
     SQLSMALLINT     BufferLength,  
     SQLSMALLINT *   StringLength2Ptr,  
     SQLUSMALLINT    DriverCompletion);

InConnectionString——表示連線字串。如果StringLength1的值為SQL_NTS,則InConnectionString必須以'\0'結尾,否則,StringLength1要指定InConnectionString的長度。

OutConnectionString——表示InConnectionString被解析完成後最終生成的連線字串。

BufferLength——表示用於存放OutConnectionString的緩衝區大小。

StringLength2Ptr——表示最終生成的OutConnectionString的長度。

三、連線中需要設定哪些屬性?

設定連線屬性的函式如下:

SQLRETURN SQLSetConnectAttr(  
     SQLHDBC       ConnectionHandle,  
     SQLINTEGER    Attribute,  
     SQLPOINTER    ValuePtr,  
     SQLINTEGER    StringLength);

常用連線屬性、屬性型別、可選屬性引數:

SQL_ATTR_CONNECTION_TIMEOUT   An SQLUINTEGER value
SQL_ATTR_LOGIN_TIMEOUT                An SQLUINTEGER value
SQL_ATTR_PACKET_SIZE                     An SQLUINTEGER value
SQL_ATTR_ACCESS_MODE                  An SQLUINTEGER value. if a data source is read-only or read-write.
    SQL_MODE_READ_ONLY
    SQL_MODE_READ_WRITE    default
SQL_ATTR_AUTOCOMMIT                     A SQLUINTEGER value
    SQL_AUTOCOMMIT_ON   default
    SQL_AUTOCOMMIT_OFF
SQL_ATTR_TXN_ISOLATION                 A 32-bit bitmask
    SQL_TXN_READ_UNCOMMITTED
    SQL_TXN_READ_COMMITTED
    SQL_TXN_REPEATABLE_READ
    SQL_TXN_SERIALIZABLE
SQL_ATTR_CONNECTION_DEAD          A read-only SQLUINTEGER value
    SQL_CD_TRUE
    SQL_CD_FALSE

這些屬性的具體說明及其它屬性的說明,請查閱參考文件。

四、如何獲取連線的屬性值?

可以通過SQLGetConnectAttr 函式獲取連線的屬性值,下面舉例說明:

SQLUINTEGER getAutoCommit(SQLHDBC hdbc) {
  SQLUINTEGER autoCommit;
  SQLRETURN retCode = SQLGetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)&autoCommit, sizeof(autoCommit), NULL);
  
  return autoCommit;
};


SQLUINTEGER getTxnIsolation(SQLHDBC hdbc) {
  SQLUINTEGER txnIsolation;
  SQLRETURN retCode = SQLGetConnectAttr(hdbc, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)&txnIsolation, sizeof(txnIsolation), NULL);

  return txnIsolation;
};

五、如何設定連線池

設定連線池需要用到的環境屬性及其可選的值:

SQL_ATTR_CONNECTION_POOLING
    SQL_CP_ONE_PER_HENV
    SQL_CP_ONE_PER_DRIVER
    SQL_CP_DEFAULT  = SQL_CP_OFF
    SQL_CP_OFF

SQL_CP_ONE_PER_HENV——表示每個環境對應一個池。這個池中可以有不同驅動的連線
SQL_CP_ONE_PER_DRIVER——表示每個驅動對應一個池。這個池中可以有從不同環境中建立的連線,只要驅動相同就會放到一個池中。

SQLHENV   henv  = SQL_NULL_HENV;
SQLRETURN retCode;

retCode = SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (SQLPOINTER*)SQL_CP_ONE_PER_HENV, 0);

retCode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);

注意,連線池屬性必須在環境控制代碼建立前設定。

六、如何從連線池中取出連線,如何釋放連線池中的連線?

 從連線池中取出連線的方式跟建立單個連線的方式相同,都是先設定連線屬性再建立連線(有些連線屬性可能在建立連線後設置)

SQLHDBC   hdbc = SQL_NULL_HDBC;
SQLRETURN retCode;

retCode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);

retCode = SQLSetConnectAttr(hdbc, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)5, 0);
retCode = SQLSetConnectAttr(hdbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retCode = SQLSetConnectAttr(hdbc, SQL_ATTR_ACCESS_MODE, (SQLPOINTER)accessMode, 0);
retCode = SQLSetConnectAttr(hdbc, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)txnIsolationLevel, 0);
retCode = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)autoCommit, 0);

SQLWCHAR outConnStr[1024];
SQLSMALLINT outConnLen;
retCode = SQLDriverConnect(hdbc, NULL, (SQLWCHAR*)connStr.c_str(), SQL_NTS, outConnStr, sizeof(outConnStr), &outConnLen, SQL_DRIVER_NOPROMPT);

 釋放連線池中的連線跟釋放單個連線使用的API相同,不同之處在於相同API背後實現的機制不同:連線池中的連線釋放後會返回連線池,後續可再取出使用,而單個連線釋放後是斷開連線。

if (hdbc != SQL_NULL_HDBC) {
  SQLDisconnect(hdbc);
  SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
  hdbc = SQL_NULL_HDBC;
}

 

參考

將連線字串關鍵字用於 SQL Server Native Client
SQLDriverConnect 函式
SQLSetConnectAttr 函式

ODBC連線池配置:

Pooling in the Microsoft Data Access Components
關於連線池環境如何建立,請查閱“SQLAllocHandle 函式”
關於連線池的配置引數的介紹,請查閱“SQLSetEnvAttr 函式”