---
title: 长事务和悬挂事务的巡检与应急方法-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于 长事务和悬挂事务的巡检与应急方法相关的常见问题和使用技巧，帮助您快速解决 长事务和悬挂事务的巡检与应急方法的难题。
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

划线反馈

# 长事务和悬挂事务的巡检与应急方法

更新时间：2025-09-04 08:41

适用版本： V2.1.x、V2.2.x、V3.1.x、V3.2.x、V4.0.x、V4.1.x、V4.2.x 内容类型：TechNote  

## 基本定义

**长事务**：事务的执行时间超过一定的阈值（业务定义），并且未执行 commit。

**悬挂事务**：事务已进入到提交阶段，并且事务的提交时间超过一定阈值。

## 巡检

### 长事务

    OceanBase 数据库 V4.1 及以上版本   OceanBase 数据库 V4.0 版本   OceanBase 数据库 V4.0 之前版本

在用户租户或者系统租户，优先使用用户租户下，可通过以下语句，查询所有长事务的事务参与者。

```sql
SELECT count(1)
FROM GV$OB_TRANSACTION_PARTICIPANTS
WHERE CTX_CREATE_TIME < date_sub(now(), INTERVAL 600 SECOND)
AND ROLE = 'LEADER'
AND ACTION = 'START';

```

上例中的 600s 表示默认的事务超时时间。

#### 注意

事务巡检前需要确保系统中不存在无主的情况。

```sql
SELECT count(1)
FROM GV$OB_TRANSACTION_PARTICIPANTS
WHERE CTX_CREATE_TIME < date_sub(now(), INTERVAL 600 SECOND)
AND STATE = 'INIT';

```

```sql
SELECT count(1)
FROM __all_virtual_trans_stat
WHERE part_trans_action<=2
  AND ctx_create_time < date_sub(now(), INTERVAL 600 SECOND)
  AND is_exiting != 1;

```

### 悬挂事务

    OceanBase 数据库 V4.1 及以上版本   OceanBase 数据库 V4.0 版本   OceanBase 数据库 V4.0 之前版本

在用户租户或者系统租户，优先使用用户租户下，可通过以下语句，查询所有悬挂事务的事务参与者。

```sql
SELECT count(1)
FROM GV$OB_TRANSACTION_PARTICIPANTS
WHERE LAST_REQUEST_TIME < date_sub(now(), INTERVAL 600 SECOND)
AND ROLE = 'LEADER'
AND ACTION <> 'START';

```

```sql
SELECT count(1)
FROM GV$OB_TRANSACTION_PARTICIPANTS
WHERE CTX_CREATE_TIME < date_sub(now(), INTERVAL 600 SECOND)
AND (STATE = 'PREPARE' OR STATE = 'REDO COMPLETE' OR STATE ='PRECOMMIT');

```

```sql
SELECT count(1) FROM __all_virtual_trans_stat
WHERE part_trans_action > 2
    AND ctx_create_time < date_sub(now(), INTERVAL 600 SECOND)
    AND is_exiting != 1;

```

## 应急方法

- 普通事务

     1. 捕获普通事务长事务。可以通过用户租户或者系统租户，优先使用用户租户查询视图 `gv$ob_transaction_participants` 来捕获普通事务长事务。如果存在长事务，获取到该事务 ID（TX_ID）、scheduler 所在节点（SCHEDULER_ADDR）以及会话 ID（SESSION_ID）。
     2. 通过 obclient 直连该事务 scheduler 所在节点上的用户租户或者系统租户，优先使用用户租户，通过 `kill session` 来回滚该事务。
 - XA 事务

     1. 捕获 XA 事务长事务。可以通过用户租户或者系统租户，优先使用用户租户查询视图 `gv$ob_transaction_participants` 来捕获 XA 事务长事务。如果存在 XA 事务长事务，获取到该 XA 事务 xid（FORMATID、GLOBALID、BRANCHID）。
     2. 登陆到 XA 事务对应的用户租户下，使用 `xa rollback` 匿名块来回滚事务。

1. 捕获长事务。可以通过用户租户或者系统租户，优先使用用户租户查询视图 `gv$ob_transaction_participants` 来捕获长事务。如果存在长事务，获取到该事务 trans id（TX_ID）、scheduler 所在节点（SCHEDULER_ADDR）以及会话 ID（SESSION_ID）。
 2. 判断该事务是否为 XA 事务。在对应的用户租户（Oracle模式）下，使用 trans ID 作为筛选条件读取 `gv$ob_global_transaction`，存在记录即为 XA 事务。

   #### 注意

   XA 事务功能目前仅在 Oracle 租户下支持。因此，视图 `GV$OB_GLOBAL_TRANSACTION` 仅可以在对应的 Oracle 租户下查询。
 3. 如果该事务为 XA 事务，在对应的用户租户下，使用 `xa rollback` 回滚事务；如果该事务为普通事务，则可以通过 obclient 直连该事务 scheduler 所在节点上的用户租户或者系统租户，优先使用用户租户 ，通过 `kill session` 来回滚该事务。

1. 识别长事务。

   ```sql
   SELECT * FROM __all_virtual_trans_stat WHERE part_trans_action<=2 AND ctx_create_time < date_sub(now(), INTERVAL 600 SECOND) AND is_exiting != 1;

   ```
 2. 判断该事务是否服务于 XA 事务分支。

   ```sql
   SELECT * FROM __all_virtual_global_transaction WHERE trans_id like '%6103238948955736893%';

   ```

   如果查询结果为空，则说明该事务为普通事务，可以执行第三步；否则，说明该内部事务服务于 XA 事务分支，可参考[XA 事务基本运维](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000001013871) 来终止该 XA 事务分支
 3. 根据上述长事务的 session_id，查询 `__all_virtual_processlist`，确定连接所在的 observer 机器，其中 svr_ip、svr_port 是 session 所在机器维护的本事务连接。

   ```sql
   select * from __all_virtual_processlist where id=3221487799;

   ```
 4. 通过用户租户或者系统租户，优先使用用户租户，直连上述的 svr_ip，kill session。

   ```sql
   kill 3221487799;

   ```

- 普通事务

     1. 捕获悬挂事务。可以通过用户租户或者系统租户，优先使用用户租户查询视图 `gv$ob_transaction_participants` 来捕获悬挂事务。
     2. 对于普通事务的悬挂场景，需要进一步分析原因，再根据原因采用对应的应急手段。
 - XA 事务

     1. 捕获 XA 悬挂事务。可以通过用户租户或者系统租户，优先使用用户租户查询视图 `gv$ob_transaction_participants` 来捕获 XA 悬挂事务。如果存在 XA 悬挂事务，获取到该 XA 事务的 xid（FORMATID、GLOBALID、BRANCHID）。
     2. 登陆到 XA 事务对应的用户租户下，使用 `xa rollback` 匿名块来回滚事务。

1. 捕获悬挂事务。可以通过用户租户或者系统租户，优先使用用户租户查询视图 `gv$ob_transaction_participants` 来捕获悬挂事务。如果存在悬挂事务，获取到该事务的 trans ID。
 2. 判断该事务是否为 XA 事务。在对应的用户租户（Oracle模式）下，使用 trans ID 作为筛选条件读取 `gv$ob_global_transaction`，存在记录即为 XA 事务。

   #### 注意

   XA 事务功能目前仅在 Oracle 租户下支持。因此，视图 `GV$OB_GLOBAL_TRANSACTION` 仅可以在对应的 Oracle 租户下查询。
 3. 如果该事务为 XA 事务，在对应的用户租户下，使用 `xa rollback` 回滚事务；如果是普通事务，则需要进一步分析悬挂原因（可能的原因包括日志流无主、磁盘爆等）。

- leader 上事务无法结束

  需要确认是否有无主，内存爆等问题，需要解决掉异常，悬挂事务才能解决掉；如果不能确定，可以联系技术支持人员协助解决。

     1. 查询事务涉及的所有表是否存在无主，首先确认事务涉及的所有 partition。

       ```sql
       SELECT svr_ip, trans_id, participants FROM __all_virtual_trans_stat
       WHERE part_trans_action > 2
           AND ctx_create_time < date_sub(now(), INTERVAL 600 SECOND)
           AND is_exiting != 1;

       ```

       根据查询结果，participants 就是该事务锁涉及的所有表信息。
     2. 对 participants 里面的每个 pkey，**分别确认**上述分区列表是否有主：**（记住，每个 pkey 都要 check）**

       ```sql
       select svr_ip, svr_port, table_id, partition_idx, role, status, replica_type from __all_virtual_clog_stat where table_id=1099511677777;

       ```

       上述查询结果，重点关注 role 这一列，如果全是 FOLLOWER，则表示无主；否则进行第三步。
     3. 确认该租户是否存在内存爆：

       ```sql
       select * from __all_virtual_tenant_memstore_info where tenant_id=1001;

       ```

       确认 `total_memstore_used` 的量是否已经到了 memstore_limit，或者其他内存异常的信息。

  如果第二步、第三步任何一种情况出现，请联系技术支持协助排查问题。
 - 备机日志回放慢，导致事务状态未推进完成

如果是这种情况，需要确认备机租户内存、网络带宽相关是否跟 Leader 异构。如果评估确实可能出现落后，紧急情况下，可以通过如下操作来尝试恢复：

1. 确认上述异常事务只在备机存在。

      1. 查询报警事务所对应的 svr_ip、`partition` 具体信息。

        ```sql
        SELECT svr_ip, svr_port, trans_id, `partition` FROM __all_virtual_trans_stat
        WHERE part_trans_action > 2
            AND ctx_create_time < date_sub(now(), INTERVAL 600 SECOND)
            AND is_exiting != 1;

        ```
      2. 根据上述查询到的 `partition` 中记录的 table_id 信息，确认当前 pkey 对应的 leader 位置。

        ```sql
        select svr_ip, svr_port from __all_virtual_clog_stat where role='LEADER' and table_id = xxx;

        ```

        如果第一步和第二步对应的 svr_ip 不同，说明异常事务在 follower 上存在。
      3. 查询上述事务对应的分区，目前集群中的记录条数：

        ```sql
        select count(1) from __all_virtual_trans_stat where trans_id like '%{选取第一步 trans_id 中的hash 字段}%' and `partition` like '%xxx%';

        ```

        如果上述查询结果为 1 条，说明只有备机上存在，可以按照预案来执行。
 2. 保留进程现场。

   ```shell
   obstack pid > /tmp/pstack.log

   ```
 3. 杀掉进程。

   ```shell
   kill -9 {pid}； // pid 为 observer 进程的 id

   ```
 4. 重新拉起进程。

   在 admin 用户下

   ```shell
   cd /home/admin/oceanbase
   ./bin/observer

   ```

## 适用版本

OceanBase 数据库 V2.x、V3.x、V4.x 版本。

上一篇

[事务 RS 相关 FAQ](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000001260180)

下一篇

[死锁检测功能不完整](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000002197441) ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
