enq TM锁冲突优化指南,三步搞定子表外键索引缺失

4 2025-08-15


有没有遇到过Oracle数据库突然变慢,AWR报告里冒出一堆enq: TM - contention等待事件,团队急得跳脚却找不到头绪?作为在运维坑里摸爬滚打十年的老DBA,今天我就拿一个真实案例,带你揪出这个问题的元凶——​​子表外键没加索引​​,顺便分享我的暴力解决三部曲。

先说说去年我碰上的事儿:某电商平台的订单库每到促销就卡成PPT。一查AWR,好家伙,enq: TM - contention等待占比30%!当时我第一反应是——​​锁表了?​​ 但翻遍日志也没人执行LOCK TABLE。接着盯上TOP SQL,发现两条高频DML:一条INSERT订单主表,一条UPDATE子表库存,单次执行Buffer Gets居然飙到​​12800+​​(正常应该就几十)。这明显不正常啊!

根据我的经验,90%的TM锁冲突都和外键索引有关。简单来说:​​当主表数据被修改时,如果子表的外键字段缺索引,Oracle就得全表扫描子表来检查约束​​。就像你拿钥匙开一栋楼的门,却要挨户试锁,能不慢吗? 所以说,问题就出在库存表的外键order_id居然没!建!索!引!

enq TM锁冲突优化指南,三步搞定子表外键索引缺失​三步搞定优化​​:

  1. ​定位问题SQL​​:
    跑个脚本查v$session,找到卡在enq: TM的会话ID,直接揪出执行中的DML语句(没AWR也能搞)。
  2. ​检查外键索引​​:
    用这个SQL查缺失索引的子表:
    sql复制
    SELECT table_name, constraint_name   
    FROM user_constraints   
    WHERE constraint_type = 'R'   
    AND (table_name, constraint_name) NOT IN (  
        SELECT table_name, index_name   
        FROM user_indexes  
    );  
  3. ​补索引+验证​​:
    比如给库存表加CREATE INDEX idx_stock_order_id ON stock(order_id),加完再跑压力测试——TM等待直接清零,订单提交速度翻倍🆙

这里有个坑要注意:别以为建了索引就万事大吉。​​索引字段顺序​​也很关键。比如订单库常按(order_id, status)查询,那把status一起塞进复合索引会更香。我吃过这亏:光建order_id索引后,高并发下还是偶发TM锁,直到把复合索引安排上才彻底消停。

总之,遇到enq: TM别慌,先盘外键索引!花5分钟查一查,可能省下几小时折腾。下次数据库再抽风,按这路子试试,说不定有惊喜。欢迎留言聊聊你的踩坑经历~

上一篇 sarch 是什么意思, 一篇文章带你彻底搞懂这个神秘缩写
下一篇:悬赏猫极速版新手任务攻略,3天赚200元的隐藏技巧
相关文章
返回顶部小火箭