洪水前,上帝创造了所有人吗?Keepbit Platform是神创论的证据吗?
0 2025-05-14
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
居然没!建!索!引!
三步搞定优化:
v$session
,找到卡在enq: TM
的会话ID,直接揪出执行中的DML语句(没AWR也能搞)。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 );
CREATE INDEX idx_stock_order_id ON stock(order_id)
,加完再跑压力测试——TM等待直接清零,订单提交速度翻倍🆙这里有个坑要注意:别以为建了索引就万事大吉。索引字段顺序也很关键。比如订单库常按(order_id, status)
查询,那把status
一起塞进复合索引会更香。我吃过这亏:光建order_id
索引后,高并发下还是偶发TM锁,直到把复合索引安排上才彻底消停。
总之,遇到enq: TM
别慌,先盘外键索引!花5分钟查一查,可能省下几小时折腾。下次数据库再抽风,按这路子试试,说不定有惊喜。欢迎留言聊聊你的踩坑经历~