如何分析enq- TM - contention_外键未建索引导致的表级锁阻塞

外键未建索引会导致主表DML时全表扫描子表校验引用,触发整表TM锁争用;通过ASH查P2得子表OBJECT_ID,再结合dba_constraints与dba_ind_columns定位缺失索引的外键。怎么确认是外键没建索引引发的 enq: TM - contention直接查 v$active_session_history 或历史 ash 视图,过滤出等待事件为 enq: tm - contention 的会话,重点看 p2 字段值------它就是被阻塞对象的 object_id。再用 dba_objects 反查这个 id 对应哪张表,大概率会发现:阻塞源头不是你正在操作的那张主表,而是它的某个子表(比如你 update tab1,但 p2 指向的是 tab2)。接着验证外键关系:SELECT * FROM dba_constraints WHERE constraint_type = 'R' AND r_constraint_name IN (SELECT constraint_name FROM dba_constraints WHERE table_name = 'TAB1' AND constraint_type = 'P'),找出所有引用 TAB1 主键的子表约束;再检查这些子表的外键列上有没有索引------没有索引的,就是根因。常见错误现象:update/delete 主表时,会话卡在 enq: TM - contention,BLOCKING_SESSION 显示另一个会话正对子表做 insert/update/commit 前的长时间事务注意:P2 是对象 ID,不是数据文件号或块号,别误查 dba_data_files如果子表是分区表,还要确认索引是否是本地(LOCAL)且覆盖全部分区,否则仍可能争用为什么外键没索引会导致子表被锁住Oracle 在主表执行 DML(尤其是 update 主键、delete 行)时,必须确保子表中没有"悬空引用"。如果没有索引,数据库只能全表扫描子表来校验一致性------这个过程需要在子表上申请 TM 锁(MODE=4,即 Share Row Exclusive),而该锁与子表上正在运行的 insert/update 事务持有的 MODE=3(Row Exclusive)不兼容,于是产生阻塞。关键点在于:这个锁不是加在某几行上,而是整张子表级别;哪怕只改主表一行,也会触发对整个子表的锁申请。场景举例:子表 ORDER_ITEMS 外键 order_id 无索引,此时有人在 insert 新订单项(未 commit),另一人想 delete ORDERS 中某条 order,就会被卡住insert 主表也会触发同样逻辑(尤其当启用 ON DELETE CASCADE 但未建索引时)并行 DML(如 /*+ APPEND */)也可能申请高阶 TM 锁,但那是另一类原因,和外键无关怎么快速找出所有缺失外键索引的子表用这段 SQL 扫一遍全库(建议在非高峰执行): Murf AI AI文本转语音生成工具

相关推荐
郑洁文4 分钟前
面向Web安全的Python渗透测试系统设计与实现
python·安全·web安全
情绪总是阴雨天~23 分钟前
智能语音分析Agent项目
python·自动化·fastapi·langgraph
SelectDB33 分钟前
从 Machine-Readable 到 Agent-Ready:面向智能体的数据库接口演进
大数据·数据库·agent
画江湖Test40 分钟前
Redis 块的原理
数据库·redis·缓存·性能优化
流烟默42 分钟前
国产数据库CERDB是什么以及服务启停
数据库·cerdb
数据库小学妹1 小时前
关系型数据库核心原理拆解:SQL解析、事务引擎、存储结构全链路分析
数据库·经验分享·sql·数据库架构·dba
海市公约1 小时前
Redis主从复制全量同步七步时序与命令传播机制详解
数据库·redis·缓存·主从复制·高可用架构·全量同步
我是唐青枫1 小时前
Java JdbcTemplate 实战指南:用 Spring 轻量完成数据库增删改查
java·数据库·spring
思麟呀1 小时前
C++11并发编程:call_once一次性执行+atomic原子类型+CAS无锁编程+自旋锁
linux·开发语言·jvm·c++·windows
梓䈑1 小时前
【MySQL】MySQL安装 和 配置
数据库·mysql