高并发插入时,enq: tx - row lock contention 是关键信号,表明事务争抢同一行锁;应优先排查主键/唯一键单点插入、分区/索引热点等问题,而非盲目调优参数。
高并发插入时,enq: tx - row lock contention 是最该盯住的信号
这说明事务在争抢同一行或相邻行的锁,不是数据库慢,是业务逻辑卡在了锁上。awr 报告里看 top 5 timed foreground events,如果 enq: tx - row lock contention 排前三,别急着加索引或调 db_cache_size,先查是不是在用主键/唯一键做高频单点插入(比如自增 id 被多个会话反复争抢)。典型场景:用 select max(id)+1 手工生成主键,或所有插入都打向同一个分区、同一个索引叶块。
用 AWR 定位具体争抢对象:查 DBA_HIST_ACTIVE_SESS_HISTORY 加 SQL_ID 和 EVENT
直接跑这段 SQL(替换时间范围):
SELECT sql_id, event, p1text, p1, p2text, p2, COUNT(*) cnt FROM dba_hist_active_sess_history WHERE sample_time BETWEEN TIMESTAMP '2024-06-10 10:00:00' AND TIMESTAMP '2024-06-10 11:00:00' AND event = 'enq: TX - row lock contention' GROUP BY sql_id, event, p1text, p1, p2text, p2 ORDER BY cnt DESC;
p1 和 p2 是锁请求的资源标识,对 TX 锁来说,p1 是锁类型(固定为 14150532),真正关键的是 p2 —— 它是事务的 USN(undo segment number)和 SLT(slot),结合 v$transaction 可反查是哪个事务在 hold 锁。更实用的做法是:拿到 sql_id 后查 DBA_HIST_SQLTEXT,确认是不是 INSERT 语句,再看执行计划是否走索引全扫描或没走绑定变量。
INSERT 优化不能只靠 APPEND,得看事务粒度和索引结构
/*+ APPEND */ 对高并发批量插入有效,但前提是:事务不长、无主键/唯一约束冲突、表没启用行级触发器。否则会触发大量 enq: TS - contention(临时段争用)或回滚段写入瓶颈。真实线上要注意三点:
- 有唯一索引的表,
APPEND插入后必须立刻COMMIT,否则后续 DML 可能因延迟索引维护而卡住 - 如果用序列(
SEQUENCE)生成主键,确保CACHE值足够大(比如CACHE 1000),避免频繁访问SEQ$表引发latch: cache buffers chains - 分区表优先按插入时间或业务维度做范围分区,并把新数据导向最新分区——减少索引叶块争用,比堆表 + 全局索引稳定得多
AWR 中容易被忽略的配套指标:gc buffer busy acquire 和 log file sync
在 RAC 环境下,并发 INSERT 如果集中在同一数据块,会出现 gc buffer busy acquire,说明远程实例正在读/写这个块,本地实例在等。这不是锁问题,是缓存一致性协议开销。这时看 AWR 的 Instance Activity Stats 部分,对比 gc cr blocks received 和 gc current blocks served,如果后者远高于前者,说明某节点成了热点块服务者。单机库则要盯紧 log file sync 平均等待时间,超过 5ms 就得检查 LOG_BUFFER 是否过小、归档是否拖慢 LGWR、存储写延迟是否突增——这些都会让 COMMIT 变慢,间接拉长事务持有锁的时间。










