写点什么

YashanDB|update/delete 没有命中数据,alter 却卡死? 其实是 TS 锁在作怪

作者:数据库砖家
  • 2025-04-21
    广东
  • 本文字数:970 字

    阅读完需:约 3 分钟

【问题分类】锁机制理解 / DDL 操作异常

【关键词】alter 超时、DDL_LOCK_TIMEOUT、TS 锁、v$transaction、无事务显示

一、问题现象描述

某客户在调整表结构时执行如下操作:

ALTER TABLE test_table RENAME COLUMN old_name TO new_name;
复制代码

结果出现了以下问题:

命令卡住迟迟未返回,最终提示超时;

查询 v$transaction 视图时未发现任何活跃事务;

无法定位是哪个会话占用资源,导致 DDL 操作无法执行。

二、关键疑点分析

为什么 DDL 卡住,但事务视图中却没有任何记录?

问题其实出在另一个会话执行了如下操作:

-- 未选中任何数据

DELETE FROM test_table WHERE id = -999;
复制代码

由于 WHERE 条件未命中任何行,看似没有影响,实际上仍然加上了 TS 级别的表锁(表空间锁),但却不会出现在 v$transaction 视图中

三、问题原理详解

1、delete/update 未命中数据 ≠ 没有锁

在 autocommit off 模式下,即便没有选中行,数据库仍会为该表分配 TS 级别锁(Table Share Lock); 此类锁不会登记在事务视图 v$transaction 中,但会存在于 v$lock 中; 这类锁会阻塞 ALTER TABLE 等 DDL 操作,导致其被卡住。

2、为什么 v$transaction 没有记录?

因为事务并未真正进入数据更改流程,未进行 undo 操作,因此未创建正式的事务上下文,也就无法出现在事务列表中。

四、解决与规避建议

1、查询锁信息方式 v$transaction 只能看到活跃事务; 遇到类似问题时,建议查询 v$lock 视图,更容易发现隐性锁(如 TS 锁):

SELECT * FROM v$lock WHERE sid IN (...);
复制代码

2、合理配置 DDL 超时时间

可通过 DDL_LOCK_TIMEOUT 参数控制 DDL 等待锁的时间,单位为秒:

-- 设置等待时间为10秒ALTER SESSION SET DDL_LOCK_TIMEOUT = 10;-- 设置为0则立即报错,不等待ALTER SESSION SET DDL_LOCK_TIMEOUT = 0;
复制代码

建议在执行重要 DDL 时开启该参数,避免长时间卡顿无反馈。

五、对比 Oracle 行为

经测试,Oracle 对于类似的 update/delete 未命中场景,同样存在:

v$transaction 无记录;

TS 锁依然存在;

会阻塞 ALTER TABLE 等 DDL;

表现一致。

因此,YashanDB 行为符合行业主流数据库设计逻辑。

六、经验总结

1.即使 delete/update 没有选中任何行,仍可能加锁,影响 DDL;

2.v$transaction 不显示,并不代表“没有锁”,建议结合 v$lock 一起排查;

3.设置合适的 DDL_LOCK_TIMEOUT,可以避免 DDL 被卡住的问题;

4.这种行为在 Oracle、YashanDB 等数据库中均为一致表现,是预期行为。

用户头像

还未添加个人签名 2025-04-09 加入

还未添加个人简介

评论

发布
暂无评论
YashanDB|update/delete 没有命中数据,alter 却卡死?其实是 TS 锁在作怪_数据库·_数据库砖家_InfoQ写作社区