如何在 Linux 上使用 C/C++ 中的 SQLServer 客户端 ODBC 驱动程序执行 XA 事务?

问题描述 投票:0回答:1

我已成功在 Windows 上使用 SQLServer OLEDB 驱动程序执行 XA 事务。现在我已经将 C++ 应用程序移植到 Linux 上。在 Linux 上,Microsoft 提供了 SQLServer 2019 ODBC 驱动程序,从该驱动程序的 17.3 版开始,据报道支持 XA。 Microsoft 提供了以下示例来说明如何实现 xa_* 函数:

使用XA事务

这个例子本身是有效的。在其他上下文中使用该代码不起作用。对 SQLSetConnectAttr(..., SQL_ATTR_ENLIST_IN_XA, ...) 操作 OP_START 的调用失败,我没有通过 CheckRC() 获得有用的信息。

  1. 如何获取有关 SQL_ATTR_ENLIST_IN_XA 失败的更多信息?
  2. 与 OLEDB 相比,XA 如何与 SQL_ATTR_ENLIST_IN_XA 方法配合使用?
  3. 是否可以更改XA模式下的隔离级别?

请与我们分享您的经验和细节。

sql-server xa
1个回答
1
投票

严格的XID数据布局

SQLSetConnectAttr(..., SQL_ATTR_ENLIST_IN_XA, ...) 函数对于 XID 非常敏感。如果 XID 有分支 ID,则分支 ID 必须从 xid_t::data 的字节 64 开始。直接在一个序列中存储像“f9707929-a367-4e3a-9a80-3fbb3a23ab11”+分支 ID“1234”这样的全局 ID,并通过 xid_t::gtrid_length 和 xid_t::bqual_length 标识字符串布局将与其他 DB API 和 IBM MQ 一起使用,但失败并显示 SQL_ATTR_ENLIST_IN_XA SQLServer。

为了获得上述示例 XID 工作,UUID 必须存储在 xid_t::data 的开头(字节 0-36),并且分支 id 必须存储在字节(64-68)处。 xid_t 字段 gtrid_length 必须设置为 36,bqual_length 设置为 4。formatID 我设置为 1。

如果 XID 布局不适合 SQL_ATTR_ENLIST_IN_XA,且操作 OP_START 失败,并且 SQLGetDiagRec() 不会报告任何内容。

设置隔离级别

默认情况下,XA 事务在隔离级别“可序列化”下运行。 Microsoft 对此隔离级别的描述如下:

交易之间完全隔离的最高级别。 SQLServer 保留对选定数据获取的读锁和写锁,以便在事务结束时释放这些锁。当 SELECT 操作使用范围 WHERE 子句时,会获取范围锁,特别是为了避免幻读。

每次调用 xa_start 时,隔离级别都设置为“可串行化”。连接后使用 SQLSetConnectAttr(..., SQL_ATTR_TXN_ISOLATION, ...) 设置隔离级别没有帮助。您必须在 SQLSetConnectAttr(..., SQL_ATTR_ENLIST_IN_XA, OP_START, ...) 之后调用此函数。

这样做允许您将隔离级别设置为 SQL_TXN_READ_COMMITTED。还将考虑数据库选项 READ_COMMITTED_SNAPSHOT。这意味着将隔离级别设置为 SQL_TXN_READ_COMMITTED 并启用数据库选项 READ_COMMITTED_SNAPSHOT 会将隔离级别切换为“快照”。

命令“DBCC useroptions”可用于查询当前会话的隔离级别。

以下查询对于检查活动事务的隔离级别和状态也很有用:

SELECT tst.session_id, [database_name] = db_name(s.database_id)
, tat.transaction_begin_time
, transaction_duration_s = datediff(s, tat.transaction_begin_time, sysdatetime()) 
, transaction_type = CASE tat.transaction_type  WHEN 1 THEN 'Read/write transaction'
                                                WHEN 2 THEN 'Read-only transaction'
                                                WHEN 3 THEN 'System transaction'
                                                WHEN 4 THEN 'Distributed transaction' END
, input_buffer = ib.event_info, tat.transaction_uow     
, transaction_state  = CASE tat.transaction_state    
            WHEN 0 THEN 'The transaction has not been completely initialized yet.'
            WHEN 1 THEN 'The transaction has been initialized but has not started.'
            WHEN 2 THEN 'The transaction is active - has not been committed or rolled back.'
            WHEN 3 THEN 'The transaction has ended. This is used for read-only transactions.'
            WHEN 4 THEN 'The commit process has been initiated on the distributed transaction.'
            WHEN 5 THEN 'The transaction is in a prepared state and waiting resolution.'
            WHEN 6 THEN 'The transaction has been committed.'
            WHEN 7 THEN 'The transaction is being rolled back.'
            WHEN 8 THEN 'The transaction has been rolled back.' END 
, trn_iso_level = CASE s.transaction_isolation_level
           WHEN 0 THEN 'Unspecified'
           WHEN 1 THEN 'ReadUncommitted'
           WHEN 2 THEN 'ReadCommitted'
           WHEN 3 THEN 'RepeatableRead'
           WHEN 4 THEN 'Serializable'
           WHEN 5 THEN 'Snapshot' END            
, transaction_name = tat.name, request_status = r.status
, tst.is_user_transaction, tst.is_local
, session_open_transaction_count = tst.open_transaction_count  
, s.host_name, s.program_name, s.client_interface_name, s.login_name, s.is_user_process
FROM sys.dm_tran_active_transactions tat 
INNER JOIN sys.dm_tran_session_transactions tst  on tat.transaction_id = tst.transaction_id
INNER JOIN Sys.dm_exec_sessions s on s.session_id = tst.session_id 
LEFT OUTER JOIN sys.dm_exec_requests r on r.session_id = s.session_id
CROSS APPLY sys.dm_exec_input_buffer(s.session_id, null) AS ib;

SQLServer ODBC 驱动程序 SQL_ATTR_ENLIST_IN_XA 的优势

使用OLEDB驱动程序和ITransactionJoin接口实现SQLServer XA,直接与本地分布式事务控制器(DTC)服务进行通信。如果 SQLServer 在另一台主机上运行,则涉及本地 DTC 和 SQLServer 主机上的 DTC。 DTC 服务必须通过网络进行通信。 RPC、动态端口范围、防火墙和安全设置通常使其很难正常工作。

使用新的 ODBC SQL_ATTR_ENLIST_IN_XA 接口,不再需要 DTC 到 DTC 的通信。该应用程序仅具有与 SQLServer 数据库实例的连接,并且在 SQLServer 主机上,DTC 服务必须运行,并且必须仅在此 DTC 中设置“XA 选项”。使用 SQL_ATTR_ENLIST_IN_XA 的应用程序不需要本地 DTC。

© www.soinside.com 2019 - 2024. All rights reserved.