使用 Microsoft JDBC Driver for SQL Server 时孤立的 XA 事务

原始 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 事务,请执行以下步骤:

  1. 使用 sys.dm_tran_active_transactions 动态管理视图 (DMV) 查询活动 XA 事务:

    SELECT transaction_id, name, transaction_state
    FROM sys.dm_tran_active_transactions
    WHERE name LIKE '%XA%';
    
  2. 检查会话 ID 为 -2 的交易:

    SELECT request_session_id, resource_type, resource_database_id
    FROM sys.dm_tran_locks
    WHERE request_session_id = -2;
    

    此 ID 表示孤单的分布式事务。

  3. 在尝试解决此问题之前,验证事务是否满足以下两个条件:

    • 事务未处于已准备(未决)状态。
    • 事务未完成恢复。

原因

如果在准备 XA 事务之前丢失了事务管理器和SQL Server之间的连接,JDBC 驱动程序不会清理这些事务。 由于 SQL Server 的 JDBC 驱动程序中 XA 的实现方式,SQL Server 无法检测到事务管理器的异常断开连接。

结果是孤立的事务在以下事件之一发生之前保持活跃状态:

  • 发生 XA 事务超时。 默认情况下,SQL Server将超时设置为无穷大。
  • SQL Server重启。

注释

XA 事务超时在 SQL Server 级别无法配置。 它需要外部处置。

解决方案

使用以下方法之一解析孤立的 XA 事务。

重启SQL Server

在生成孤立事务的任何 JVM 故障或网络中断后重启SQL Server。 重启会清除内存中事务引用。

手动终止孤儿事务

  1. 运行以下查询以识别和停止在应用程序恢复中幸存的事务:

    SELECT transaction_id, name
    FROM sys.dm_tran_active_transactions
    WHERE name LIKE '%XA%';
    
  2. 找到孤立事务的 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 事务的风险: