暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

人大金仓数据库KingbaseES DCI连接模块的处理过程

原创 数据猿 2023-12-12
868


金仓数据库KingbaseES———DCI连接模块的处理过程

关键字:

DCI、连接建立、连接释放、人大金仓、KingbaseES

DCI连接配置

DCI连接数据库支持配置文件服务名的连接方式,通过设置数据库服务句柄、结合用户名、密码认证连接到服务器。一般情况下,sys_service.conf文件中的配置项包含:

host 数据库服务器的地址,包括域名、主机名、主机的 IP 地址等。

port 端口号

dbname 数据库名

DCILog 指定日志信息文件的保存路径。

DCILogLevel 指定日志级别。

UseDciDat数据库中的 timestamp 类型的处理方式。

AutoCommit 是否采用自动提交事务方式,默认是 1,表示采用自动提交模式;如果指定为 0,表示采用手动提交模式。

BatchInsertSize_Ext 批量 DML 扩展优化。

SSLMode SSL 加密连接的方式。

pqopt SSL 加密连接相关的从属配置。

同时支持以“IP:PORT:DBNAME”方式连接数据库,使用这种方式时,需要将配置文件sys_service.conf中的服务名改为“Default”,使配置将生效。如果在配置文件找不到“Default”服务名、或者环境变量找不到配置文件,则 sys_service.conf 文件中服务名为“Default”的配置将生效,即类Oracle的默认值模式。

AutoCommit=0

AutoCommitDDL=1

BatchInsertSize_Ext=1

Protocol=7.4-2

DCI应用程序有两套默认值,服务名映射方式连接数据库情况下AutoCommit=1、BatchInsertSize_Ext=0配置参数生效(自动提交),连接串形式连接数据库情况下类oracle模式生效。两套默认值的不同在于:原默认值中默认 AutoCommit=1,并且不配置 BatchInsertSize_Ext,即默认该配置为 0;类 Oracle 默认值则开启上述四个配置。

DCI支持的事务模式如表1所示。

表1 DCI支持的事务模式

序号

事务模式

事务项配置

事务场景

1

手动提交事务模式场景

AutoCommit=0

服务名映射连接

2

自动提交事务模式场景

AutoCommit=1

默认事务模式

1)服务名映射连接;

2)连接串模式sys_service.conf没有Default服务名

3

语句级事务回滚模式场景

AutoCommit=0

Protocol=7.4-2

服务名映射连接

4

DDL语句自动提交事务模式场景

AutoCommit=0

AutoCommitDDL=1

服务名映射连接

6

“Default”服务名模式场景

自定义模式

连接串形式连接

5

类oracle事务模式场景

AutoCommit=0

Protocol=7.4-2

AutoCommitDDL=1

BatchInsertSize_Ext=1

默认事务模式

  1. 连接串形式连接,配置文件没有“Default”服务名映射。
  2. KINGBASE_CONFDIR环境变量制定路径下,没有sys_service.conf配置文件。

DCI连接建立

DCI连接数据库建立在成功初始化各项句柄的前提下,主要进行的工作是连接相关句柄的空间申请和域数据库建立连接,值得注意的是读写分离过程中主从连接建立与负载均衡策略。在DCI提供的接口中,连接建立仅通过DCISessionBegin( )实现,函数定义为:

sword DCISessionBegin(DCISvcCtx *svchp,

DCIError *errhp,

DCISession *usrhp,

ub4 credt,

ub4 mode)

DCISessionBegin( )内部的调用关系如图1所示。

C:\Users\yangli\Desktop\OCI接口函数调用\DCISessionBegin实现.png

图1 DCISessionBegin( )函数调用关系

  1. 执行ociret = GetConnInfo(svchp->pServer->dblink, usrhp);读取连接信息,若是采用读写分离,连接服务器集群(服务器数量>1),申请增加的连接句柄ConnectionClass

ret = KSAPI_AllocConnect(pSession->pEnv->henv, (HDBC *)&con);

KSAPI_AllocConnect

RETCODE KSQL_API KSAPI_AllocConnect(HENV henv, HDBC * phdbc)

在环境句柄下分配连接句柄conn。

在申请到从属服务器连接的空间之后,将其赋值给主连接(在句柄分配时已经完成配置)的下一个节点,将主连接current的配置参数拷贝到新申请的空间中,继续申请并配置下一个节点

current->nextConnection = con;

KSAPI_ConnectionCopy(con,current);

current = current->nextConnection;

KSAPI_ConnectionCopy

RETCODE KSQL_API

KSAPI_ConnectionCopy(HDBC destHdbc, const HDBC srcHdbc)

拷贝已有连接句柄的connInfo结构体参数到新的连接句柄,没有错误设置

调用GetConnInfo失败后执行

InternalSetError(errhp, SQL_HANDLE_DBC, svchp->pSession->hdbc, 65001, "Can not find sys_service.conf", "00000");

② 与服务器建立连接,涉及到ConnectionClass:

ret = KSAPI_DriverConnect(hdbc, NULL, connIn, (KSQLSMALLINT)strlen(connIn), connOut, 8192, &cbOut, KSQL_DRIVER_NOPROMPT);

KSAPI_DriverConnect

RETCODE

KSQL_API KSAPI_DriverConnect(HDBC hdbc, HWND hwnd,

const KSQLCHAR * szConnStrIn,

KSQLSMALLINT cbConnStrIn,

KSQLCHAR * szConnStrOut,

KSQLSMALLINT cbConnStrOutMax,

KSQLSMALLINT * pcbConnStrOut,

KSQLUSMALLINT fDriverCompletion)

错误设置:调用CC_set_error(conn, CONN_ERR_OPENDB_ERROR, "Connection string parse error", func);在ConnectionClass上设置错误,调用

retval = CC_connect(conn, salt);

执行真正的连接操作。

CC_connect

char CC_connect(ConnectionClass *conn, char *salt_para)

ODBC层的连接操作。内部调用ret = LIBPQ_CC_connect(conn, salt_para);建立连接:

  1. 首先初始化日志;
  2. 再调用retval = LIBPQ_connect(conn);建立连接并在连接句柄conn上设置错误信息:CC_set_error(conn, CONN_ERR_OPENDB_ERROR, emsg, func);该函数成功返回1,失败返回0或者-1;
  3. 调用res = CC_send_query(conn, setsql, NULL, READ_ONLY_QUERY, NULL);获取结果集,内部调用CC_send_query_append,通过CC_set_error在连接句柄conn上设置错误信息。
  4. 对结果集res进行处理,不设置错误信息。

调用CC_set_translation对win32平台进行转换处理,并设置错误信息。该函数不接受返回值,故而执行出错后不做处理。

调用CC_send_settings,并在连接句柄conn上进行错误设置:

  1. 调用KSAPI_AllocStmt申请临时语句句柄;
  2. 调用KSAPI_ExecDirect执行相应的配置语句,ODBC层的语句执行流程,在临时语句句柄上进行错误消息设置;
  3. 调用KSAPI_FreeStmt释放临时语句句柄。

后续对于连接的处理:CC_lookup_lo(conn)、CC_determine_locale_encoding(conn)、CC_get_mode(conn)、CC_get_supportNewInterval(conn)、CC_get_extend_typeoid(conn)、CC_get_supportNewRowid(conn)、CC_send_client_encoding(conn, conn->client_encoding ? conn->client_encoding : conn->locale_encoding)等都会对连接句柄conn设置错误码。

③ 连接申请之后,需要设置相应的属性

ret = KSAPI_SetConnectAttr(hdbc, KSQL_ATTR_AUTOCOMMIT, (PTR) KSQL_AUTOCOMMIT_ON, KSQL_IS_INTEGER);

KSAPI_SetConnectAttr

RETCODE KSQL_API KSAPI_SetConnectAttr(HDBC ConnectionHandle,

KSQLINTEGER Attribute, PTR Value,

KSQLINTEGER StringLength)

根据是否自动提交设置连接句柄的各种属性,若是不支持的属性,调用

CC_set_error(conn, CONN_ERR_OPTION_NOT_FOR_THE_DRIVER, msg, func);

在ConnectionClass上设置错误信息

在KSAPI_SetConnectAttr内部,调用KSAPI_SetConnectOption设置操作属性:

KSAPI_SetConnectOption

RETCODE KSQL_API KSAPI_SetConnectOption(HDBC hdbc,

KSQLUSMALLINT fOption,

KSQLULEN vParam)

调用

CC_set_error(conn, CONN_ERR_TRANSACT_IN_PROGRES, "Cannot switch isolation level while a transaction is in progress", func);

在ConnectionClass上设置错误信息

在KSAPI_SetConnectOption内部,调用CC_set_transact,内部在ConnectionClass设置错误消息:

CC_set_error(conn, CONN_ERR_EXEC_ERROR, "ISOLATION change request to the server error", __FUNCTION__);

④ 如果当前建立连接的IP序列号为0,调用KSAPI_DriverInit取消连接:

ret = KSAPI_DriverInit(hdbc, NULL, connIn, (KSQLSMALLINT)strlen(connIn), connOut, 8192, &cbOut, KSQL_DRIVER_NOPROMPT);

KSAPI_DriverInit

RETCODE KSQL_API

KSAPI_DriverInit(HDBC hdbc, HWND hwnd, const KSQLCHAR * szConnStrIn,

KSQLSMALLINT cbConnStrIn, KSQLCHAR * szConnStrOut,

KSQLSMALLINT cbConnStrOutMax,

KSQLSMALLINT * pcbConnStrOut,

KSQLUSMALLINT fDriverCompletion)

通过以下函数设置错误消息:

CC_set_error(conn, CONN_ERR_OPENDB_ERROR, "Connection string parse error", func);

⑤ 如果所有连接都未建立成功,调用下面函数获取错误信息,获取EnvironmentClass 、ConnectionClass、StatementClass、DescriptorClass四类底层错误,并设置到errhp句柄上:

ret = KSAPI_GetDiagRec(KSQL_HANDLE_DBC, usrhp->hdbc, 1, sqlstate, (KSQLINTEGER *) &error_code, msg, 256, NULL);

KSAPI_GetDiagRec

RETCODE KSQL_API

KSAPI_GetDiagRec(KSQLSMALLINT HandleType, KSQLHANDLE Handle,

KSQLSMALLINT RecNumber, KSQLCHAR *Sqlstate,

KSQLINTEGER *NativeError, KSQLCHAR *MessageText,

KSQLSMALLINT BufferLength, KSQLSMALLINT *TextLength)

内部涉及KSAPI_EnvError(environ.c)、KSAPI_ConnectError(environ.c)、KSAPI_StmtError(statement.c)、KSAPI_DescError(descriptor.c)的错误消息获取。

DCI连接释放

在程序执行结束后,需要断开与服务器的连接,释放会话资源。在DCI中,主要通过接口DCISessionEnd( )实现,函数定义如下所示:

sword DCISessionEnd(DCISvcCtx *svchp, DCIError *errhp,

DCISession *usrhp, ub4 mode)

程序运行结束后,结束会话,释放申请的ODBC连接句柄和语句句柄。错误设置:包含错误句柄errhp,可以向下传入。

释放连接时调用KSAPI_Disconnect(hdbc);执行时设置错误。

KSAPI_Disconnect

RETCODE KSQL_API KSAPI_Disconnect(HDBC hdbc)

断开与数据库服务器的连接,若是当前连接有事务执行,设置错误:

CC_set_error(conn, CONN_ERR_IN_USE, "A transaction is currently being executed.", func);

内部调用CC_cleanup执行操作:

char CC_cleanup(ConnectionClass *conn, BOOL keepCommunication)

CC_cleanup内部释放当前连接conn下的描述句柄时调用

void    DC_Destructor(DescriptorClass *desc)

内部依次释放conn->num_descs 个DescriptorClass的错误消息__error_message,错误句柄ER_Destructor(deschd->kserror)。


「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论