row cache lock等待是真实的数据字典缓存争用,并非锁故障;需通过v$rowcache或v$active_session_history定位具体争用项(如dc_sequences、dc_users),再针对性优化序列缓存、拦截错误登录或错峰ddl。
row cache lock 等待不是锁故障,而是真实的数据字典缓存争用——只要看到它持续出现,说明有会话正在高频修改或反复验证某类元数据(比如序列值、用户权限、对象定义),其他会话被迫排队等读。调大共享池或杀会话只能缓解表象,不查 v$rowcache 或 v$active_session_history 就动手,大概率白忙。
查清是哪类字典缓存被争用
别只盯着“row cache lock”这个事件名,必须定位到具体缓存项。两个入口最直接:
- 看
v$rowcache中谁的GETMISSES和MODIFICATIONS同时偏高:SELECT parameter, gets, getmisses, modifications FROM v$rowcache WHERE getmisses > 1000 ORDER BY getmisses DESC;常见组合:dc_sequences(高频NEXTVAL)、dc_users(错误密码重试)、dc_objects(DDL 集中执行) - 用
v$active_session_history关联等待源头:SELECT p1, COUNT(*) c FROM v$active_session_history WHERE event = 'row cache lock' AND sample_time > SYSDATE - 1/24 GROUP BY p1 ORDER BY c DESC;拿到最高频的p1值(如 8),再查对应缓存名:SELECT parameter FROM v$rowcache WHERE cache# = 8;
针对 dc_sequences 争用:必须设 CACHE,且避开 ORDER
RAC 或高并发单实例下,NOCACHE 序列等于主动制造阻塞——每次 NEXTVAL 都要更新 seq$ 表并持 SSX 锁,所有并发请求全卡在 dc_sequences 上。
-
ALTER SEQUENCE order_seq CACHE 1000;—— RAC 环境最低建议 1000,单实例可从 500 起步 - 禁用
ORDER(除非业务真要求跨实例严格连续):CREATE SEQUENCE log_id NOORDER CACHE 1000; - Oracle 12c+ 可加
SESSION级缓存,彻底隔离会话间竞争:ALTER SEQUENCE seq_name CACHE 1000 SESSION; - 避免在 PL/SQL 循环里反复
SELECT seq.NEXTVAL INTO ...,改用单次INSERT ... VALUES (seq.NEXTVAL)
识别 dc_users 争用:别忽略登录失败的连锁反应
Oracle 11g+ 默认启用登录延迟机制:同一用户连续 3 次输错密码后,后续所有连接(含正确密码)都会卡在 dc_users 的 row cache lock 上,且延迟时间指数增长。
- 确认是否为此原因:
SELECT username, returncode, COUNT(*) FROM dba_audit_trail WHERE returncode = 1017 AND timestamp > SYSDATE - 1/24 GROUP BY username, returncode ORDER BY 3 DESC; - 临时绕过(仅限紧急):
ALTER SYSTEM SET EVENTS '28401 trace name context forever, level 1';(重启失效,且暴露暴力破解风险) - 根本解法:定位客户端 IP 和应用账户,修复硬编码密码;或收紧
FAILED_LOGIN_ATTEMPTS并启用账户锁定策略
减少 DDL 和硬解析对 dc_objects 的冲击
批量建表、加字段、改权限这些操作,本质是高频写 dc_objects 和 dc_users,尤其在部署脚本中集中执行时,极易引发连锁等待。
- 避免高峰时段执行 DDL;若必须批量操作,用
DBMS_LOCK.SLEEP在应用层随机化执行时间,打散请求峰 - 强制使用绑定变量:
SELECT * FROM t WHERE id = :id,而非拼接 SQL;否则每次文本不同都会触发硬解析,反复访问dc_objects - 检查是否启用了 19c 实时统计信息(
dc_realtime_tabst):若表数据变更极快,该特性反而加重字典争用,可考虑关闭:ALTER TABLE t SET STATISTICS_TRACKING = FALSE;
真正棘手的点往往藏在细节里:比如 RAC 下 dc_sequences 争用默认超时是 60 秒,而单实例只有 3 秒,误判成“锁没释放”就容易走错排查方向;又比如 p2=5(KQRMX,排他锁)和 p3=3(KQRMS,共享锁)同时大量出现,说明一个 DDL 操作长期未提交,而不是并发问题——这些信号不结合 p2/p3 和 sql_opname 看,很容易被忽略。











