昨天做压测的时候系统突然报警,说有8个长事务卡住了。
具体场景是这样的:
这8个事务其实都很简单
每个事务都是连续执行3条类似的SQL,更新同一行数据
最后实在没办法,只能手动kill了这些会话
现在主要有两个疑问:
- 这到底是不是死锁啊?因为OCP页面上没看到死锁的提示
- 如果不是死锁的话,为什么会出现这种情况呢?
补充说明几个关键点:
压测时并发量挺大的
监控上看到是被卡住,不是立即报错
事务内容就是简单的update,没有复杂逻辑
这种情况该怎么排查?有没有可能:
是行锁等待超时?
还是说单纯因为并发更新同一行导致的排队?
需要看哪些具体的日志或监控指标?
仗剑天涯
#3
- 长事务的原因分析
根据文档片段 10 的描述,长事务是指事务开始后,执行时间超过 60 秒不提交的事务。在您的场景中,三个简单的 UPDATE 语句连续更新同一行数据,导致事务持续时长达到 32 分 22.9 秒,这符合长事务的定义。
可能原因:
行锁冲突:根据文档片段 3,当多个事务并发更新同一行数据时,可能会出现行锁冲突。如果前一个事务未提交或未释放锁,后续事务会等待,从而导致事务持续时间变长。
业务逻辑问题:如果这些 UPDATE 语句没有及时提交或回滚,可能导致事务长时间挂起。
热点行问题:文档片段 3 提到,热点行更新是关系型数据库的通用问题。如果频繁更新同一行数据,可能会引发锁冲突和性能瓶颈。
2. 是否为死锁?
从您的描述来看,OCP 页面上没有提示死锁,因此可以初步判断当前问题并非死锁引起。
论坛小助手
#5
根据您提供的信息,这种现象不一定是死锁。因为死锁通常涉及多个事务互相等待对方持有的资源,而从您的描述来看,8个事务都在尝试更新同一行数据,这更像是并发行锁竞争问题。OceanBase数据库中,行锁等待超时机制可以帮助解决此类问题,但并不是唯一的解决方案。
解决方案:
-
设置合理的锁超时时间:您可以调整租户参数
ob_trx_lock_timeout
,设置一个合理的锁超时时间,这样如果某个事务长时间无法获取锁,就会自动回滚,避免整个系统被长时间阻塞。ALTER SYSTEM SET ob_trx_lock_timeout = 10000; -- 设置为10秒
-
检查并优化事务逻辑:尽量减少事务的执行时间,避免不必要的事务嵌套和长时间持有锁。
-
限制并发量:如果并发量过大,可以考虑降低并发量,减少行锁的竞争。
-
使用
SELECT FOR UPDATE WAIT
:可以在更新前使用 SELECT FOR UPDATE WAIT
语句,指定等待时间,这样可以更精细地控制锁的等待时间。SELECT * FROM table WHERE condition FOR UPDATE WAIT 1; -- 最多等待1秒
-
查看死锁检测:虽然您没有看到死锁提示,但可以检查 OCP 页面的死锁检测功能,确认是否发生了死锁。
SELECT * FROM oceanbase.DBA_OB_DEADLOCK_EVENT_HISTORY;
-
监控和日志:查看
GV$OB_SQL_AUDIT
视图,分析 SQL 执行情况,特别是锁等待时间和事务执行时间。SELECT * FROM GV$OB_SQL_AUDIT WHERE SQL_ID = 'your_sql_id';
相关文档片段:
-
长事务的影响:长事务的存在易造成大量的阻塞和锁超时,影响其他事务的执行。(文档ID: 2645, 2698)
-
OceanBase 事务类型:事务按照执行的时间和状态可以分为其他事务、长事务、悬挂事务三种。其中,长事务和悬挂事务会导致资源长时间不释放,等待会话长时间被阻塞,影响业务系统。(文档ID: 4776)
-
超时机制:OceanBase 提供了锁超时机制、语句超时机制和事务超时机制来解决死锁问题。(文档ID: 7684)
-
锁冲突排查:当遇到对特定的行进行并发更新的情况,很容易出现行锁冲突问题。(文档ID: 19727)
检索到的文档如下:
- ob_server_exists_long_lived_trans OB 服务器存在长事务
- ob_tenant_long_trans_exist OB 租户存在长事务
- XA 事务和悬挂事务诊断
- 锁机制
- 分析诊断&决策流程
cwa
#6
更新同一行不会死锁,死锁按照obv4是会直接监测到然后报错解锁的,应该是长事务等待