原始 KB 数: 3005016
总结
使用 XA 事务,包括在 Microsoft JDBC Driver for SQL Server 环境下使用时,你可能会看到运行 Microsoft SQL Server 的服务器上会有遗留的事务保持挂起。 当事务管理器在 XA 事务完成之前停止响应或失去与基于SQL Server的服务器的连接时,通常会发生这些孤立事务。 本文介绍 SQL Server 中孤立无关联的 XA 事务的症状、原因、诊断步骤和解决策略。
症状
可能会遇到以下一个或多个问题:
- 事务在SQL Server中长时间处于挂起状态。
- 事务在数据库中显示,需要具有
NULL或-2会话ID。 - 事务无限期地阻止其他事务,并导致锁定超时和冻结线程。
验证孤儿 XA 事务
若要验证孤立的 XA 事务,请执行以下步骤:
使用 sys.dm_tran_active_transactions 动态管理视图 (DMV) 查询活动 XA 事务:
SELECT transaction_id, name, transaction_state FROM sys.dm_tran_active_transactions WHERE name LIKE '%XA%';检查会话 ID 为
-2的交易:SELECT request_session_id, resource_type, resource_database_id FROM sys.dm_tran_locks WHERE request_session_id = -2;此 ID 表示孤单的分布式事务。
在尝试解决此问题之前,验证事务是否满足以下两个条件:
- 事务未处于已准备(未决)状态。
- 事务未完成恢复。
原因
如果在准备 XA 事务之前丢失了事务管理器和SQL Server之间的连接,JDBC 驱动程序不会清理这些事务。 由于 SQL Server 的 JDBC 驱动程序中 XA 的实现方式,SQL Server 无法检测到事务管理器的异常断开连接。
结果是孤立的事务在以下事件之一发生之前保持活跃状态:
- 发生 XA 事务超时。 默认情况下,SQL Server将超时设置为无穷大。
- SQL Server重启。
注释
XA 事务超时在 SQL Server 级别无法配置。 它需要外部处置。
解决方案
使用以下方法之一解析孤立的 XA 事务。
重启SQL Server
在生成孤立事务的任何 JVM 故障或网络中断后重启SQL Server。 重启会清除内存中事务引用。
手动终止孤儿事务
运行以下查询以识别和停止在应用程序恢复中幸存的事务:
SELECT transaction_id, name FROM sys.dm_tran_active_transactions WHERE name LIKE '%XA%';找到孤立事务的 ID 后,在 Java 中使用 XAResource 执行提交或回滚操作。 例如:
提交
XAResource xaRes = xaConnection.getXAResource(); xaRes.commit(xaTransactionId, bOnePhase);回滚
XAResource xaRes = xaConnection.getXAResource(); xaRes.rollback(xaTransactionId);
配置 XA 事务超时
设置 XA 超时以强制自动清理孤立事务。 超时值应比运行时间最长的事务长。 例如:
XAResource xaRes = xaConnection.getXAResource();
xaRes.setTransactionTimeout(600); // Timeout in seconds
注释
许多第三方事务管理器不会公开 XAResource。 在这些情况下,使用外部管理应用全局设置默认超时值。
预防最佳实践
遵循以下准则,降低孤立 XA 事务的风险:
请确保 MS DTC 服务在所有参与节点上都运行并配置了 XA。 有关 SQL Server on Linux,请参阅 如何在 Linux 上配置 Microsoft Distributed Transaction Coordinator (MSDTC)。
应用 MS DTC 安全设置,并在
dcomcnfg中启用 XA 事务。使用 JDBC XA 属性:
xaTransactionTimeout=600 loginTimeout=30