长事务问题咨询

今天压力测试系统告警存在长事务 存在三个长事务。
会话ID:3221491694,事务ID:80186255,事务类型:unknown,事务创建时间:2025-04-15T11:14:01.953+08:00,事务最长持续时长:32 分 22.9 秒。这是三个简单的update语句,连续三个相似sql更新同一行数据,后通过kill会话处理
请问下出现这个问题的原因是什么呢,死锁吗,如果是死锁我该怎么排查呢 我看ocp页面上没有提示有死锁

1 个赞

@论坛小助手

1 个赞

根据文档库中的信息,以下是对您问题的详细解答:

1. 长事务的原因分析

根据文档片段 10 的描述,长事务是指事务开始后,执行时间超过 60 秒不提交的事务。在您的场景中,三个简单的 UPDATE 语句连续更新同一行数据,导致事务持续时长达到 32 分 22.9 秒,这符合长事务的定义。

可能原因:

  • 行锁冲突:根据文档片段 3,当多个事务并发更新同一行数据时,可能会出现行锁冲突。如果前一个事务未提交或未释放锁,后续事务会等待,从而导致事务持续时间变长。
  • 业务逻辑问题:如果这些 UPDATE 语句没有及时提交或回滚,可能导致事务长时间挂起。
  • 热点行问题:文档片段 3 提到,热点行更新是关系型数据库的通用问题。如果频繁更新同一行数据,可能会引发锁冲突和性能瓶颈。

2. 是否为死锁?

从您的描述来看,OCP 页面上没有提示死锁,因此可以初步判断当前问题并非死锁引起。

死锁排查方法:

尽管当前不是死锁问题,但如果您怀疑存在死锁,可以通过以下步骤排查:

  • 检查死锁检测功能是否开启:根据文档片段 4 和 5,OceanBase 社区版 OCP 暂不支持死锁检测功能。但您可以启用 OceanBase 数据库的分布式死锁自动检测功能(从 V3.2 版本开始支持)。
  • 查询死锁历史视图:通过查询 DBA_OB_DEADLOCK_EVENT_HISTORYCDB_OB_DEADLOCK_EVENT_HISTORY 视图,获取过去发生的死锁事件及其相关信息。示例如下:
    obclient> SELECT * FROM oceanbase.DBA_OB_DEADLOCK_EVENT_HISTORY;
    obclient> SELECT * FROM oceanbase.CDB_OB_DEADLOCK_EVENT_HISTORY;
    
  • 超时机制排查:根据文档片段 2,OceanBase 提供了锁超时机制 (ob_trx_lock_timeout)、语句超时机制 (ob_query_timeout) 和事务超时机制 (ob_trx_timeout) 来解决死锁问题。您可以检查这些参数的配置是否合理。

3. 解决方案

针对当前的长事务问题,建议采取以下措施:

(1) 优化业务逻辑

  • 确保每个事务在完成操作后立即提交或回滚,避免事务长时间挂起。
  • 如果需要连续更新同一行数据,考虑将多个 UPDATE 语句合并为一个事务,减少锁等待时间。

(2) 调整超时参数

根据文档片段 2,您可以调整以下参数以减少锁等待时间:

  • ob_trx_lock_timeout:设置锁等待超时时间。
  • ob_query_timeout:设置语句执行超时时间。
  • ob_trx_timeout:设置事务执行超时时间。

(3) 使用 SELECT ... FOR UPDATE WAIT 优化锁等待

根据文档片段 3,您可以使用 SELECT ... FOR UPDATE WAIT 语法来控制锁等待时间。例如:

SELECT * FROM your_table WHERE id = ? FOR UPDATE WAIT 1;

上述语句会在等待 1 秒后超时,避免事务长时间挂起。

(4) 监控和告警

  • 在 OCP 中监控长事务和悬挂事务的告警信息,及时发现并处理异常事务。
  • 根据文档片段 10,OCP 中长事务的告警阈值为 30 秒,悬挂事务的告警阈值为 10 分钟。确保这些阈值符合您的业务需求。

4. 总结

当前问题更可能是由于行锁冲突或业务逻辑问题导致的长事务,而非死锁。建议优化业务逻辑、调整超时参数,并使用 SELECT ... FOR UPDATE WAIT 语法来减少锁等待时间。同时,加强监控和告警机制,及时发现并处理异常事务。

如果仍有疑问,可以联系 OceanBase 的人工答疑团队获取进一步支持。

更多信息请查看:

  1. XA 事务和悬挂事务诊断
  2. 锁机制
  3. 分析诊断&决策流程
  4. 死锁检测
  5. 6000 ~ 6999
  6. ob_tenant_large_trans_exist OB 租户存在大事务
  7. 事务概览
1 个赞

死锁是会话之间的相互锁是一个环,你这个应该说是出现了一个会话持有了行锁没有提交,导致后面的会话一直在重试,下次可以查询gv$ob_locks看下是否存在锁的争抢select
/+DYNAMIC_SAMPLING(1)/
concat(‘kill ‘,c.svr_ip,’ /’,c.svr_ip,’:2881/’) as kill_sid,
b.database_name,
b.table_name,
a.svr_ip,
case when block = 0 then ‘持有锁会话’ ELSE ‘等待锁会话’ END AS block,
c.id,
a.type,
a.trans_id,
a.id2,
a.lmode,
a.CTIME / 1000000 as CTIME,
c.info,
c.command,
c.time,
c.total_time,
c.user_client_ip,
c.retry_cnt,
c.retry_info,
c.thread_id,
c.trace_id
from
gv$ob_locks a,
cdb_ob_table_locations b,
gv$ob_processlist c
where
a.id1 = b.tablet_id
and a.tenant_id = b.tenant_id
and c.trans_id = a.trans_id
and b.tenant_id = 租户ID
and b.role = ‘LEADER’
and id2 is not null;

2 个赞