
Oracle 数据库 row cache read 等待事件深度解析
1. 等待事件本质
row cache read:
当会话需要从数据字典缓存(Row Cache)中读取条目时发生的物理I/O等待。Row Cache存储关键数据字典信息(如表定义、列信息、权限、序列元数据等),通常在内存中访问。当所需条目不在内存中时,需从磁盘读取。- 关键特性:
- 本质是物理I/O操作(从SYSTEM/SYSAUX表空间读取)
- 区别于
row cache lock(并发控制等待) - 高频率出现表明字典缓存效率低下
- 与相关等待的区别:
特性 row cache readrow cache locklibrary cache: mutex S触发原因 字典缓存缺失 字典条目争用 库缓存访问争用 等待类型 I/O等待 锁等待 轻量级锁争用 解决方案 增加缓存/优化访问 减少DDL/序列争用 减少硬解析
2. 产生过程详解
- 会话请求字典数据:
会话需要访问数据字典(如获取表结构、序列定义) - 检查行缓存:
在Row Cache中查找所需条目 - 缓存未命中:
若条目不在内存中(首次访问或已被老化) - 触发物理读取:
会话发起磁盘I/O,等待事件记为row cache read - 读取数据文件:
从SYSTEM/SYSAUX表空间读取基表数据(如sys.obj$) - 加载到缓存:
将数据加载到Row Cache中 - 返回数据:
将会话请求的数据返回
3. 高频场景
首次访问对象
-- 新部署的存储过程首次执行
BEGIN new_proc; END; -- 需加载过程定义
序列元数据获取
-- 序列首次调用
SELECT order_seq.NEXTVAL FROM dual; -- 加载序列定义
字典缓存刷新后
-- DBA手动刷新缓存
ALTER SYSTEM FLUSH SHARED_POOL; -- 清除缓存
-- 后续访问需重新加载
SELECT * FROM user_tables; -- 触发row cache read
实例启动初期
- 数据库刚启动,字典缓存为空
- 所有字典访问均需磁盘读取
元数据查询
-- 监控系统频繁查询
SELECT * FROM dba_objects; -- 需加载大量字典条目
4. 根本原因分类
应用层问题
| 问题类型 | 典型案例 |
|---|---|
| 对象首次部署 | 上线新功能 → 大量存储过程首次执行 |
| 序列首次调用 | 新业务表插入 → 首次使用关联序列 |
| 高频字典查询 | 监控系统每5秒执行SELECT * FROM dba_tables |
| 动态对象创建 | 应用运行时执行CREATE GLOBAL TEMPORARY TABLE temp1 ... |
数据库配置
- 共享池过小:
SHOW PARAMETER shared_pool_size; -- < 总内存10% 风险高 - 字典缓存不足:
SELECT SUM(bytes)/1048576 FROM v$sgastat WHERE name = 'row cache'; -- < 50MB 不足 - 序列参数不当:
CREATE SEQUENCE order_seq NOCACHE; -- 导致频繁访问序列定义
系统资源瓶颈
- I/O性能差:
SYSTEM/SYSAUX表空间位于慢速磁盘(HDD) - 内存压力:
共享池频繁换页 → 字典条目老化
Oracle内部机制
- Bug导致缓存失效:
- Bug 12902068:11g中序列访问导致缓存异常失效
- Bug 21382587:12c中字典统计信息收集引发缓存刷新
- 字典表分析缺失:
SYS对象统计信息陈旧导致优化器决策错误
5. 深度排查流程
步骤1:系统级诊断
-- 确认等待强度
SELECT event, total_waits, time_waited_micro
FROM v$system_event
WHERE event = 'row cache read';
-- 关联字典缓存效率
SELECT
(SELECT sum(getmisses)/sum(gets) FROM v$rowcache) miss_ratio,
(SELECT bytes/1048576 FROM v$sgastat WHERE name = 'row cache') cache_size_mb
FROM dual;
- 严重性阈值:
time_waited_micro> 30秒/分钟 +miss_ratio> 0.1
步骤2:定位热点字典
-- 行缓存未命中统计
SELECT
cache#,
type,
gets,
getmisses,
ROUND(getmisses*100/DECODE(gets,0,1,gets),2) miss_pct,
modifications
FROM v$rowcache
WHERE getmisses > 1000
ORDER BY getmisses DESC;
-- 常见高负载类型
/*
dc_objects : 对象定义
dc_sequences : 序列定义
dc_tablespaces : 表空间信息
dc_users : 用户信息
dc_constraints : 约束信息
*/
步骤3:分析触发SQL
-- ASH历史分析
SELECT
sql_id,
COUNT(*) waits,
current_obj#
FROM v$active_session_history
WHERE event = 'row cache read'
AND sample_time > SYSDATE - 10/1440 -- 近10分钟
GROUP BY sql_id, current_obj#
ORDER BY waits DESC;
-- 关联SQL文本
SELECT sql_id, sql_text FROM v$sql WHERE sql_id IN ('&sql_id1','&sql_id2');
步骤4:检查对象状态
-- 高频访问序列
SELECT
sequence_owner,
sequence_name,
cache_size,
order_flag
FROM dba_sequences
WHERE sequence_name IN (
SELECT object_name FROM v$active_session_history
WHERE event='row cache read'
AND object_type='SEQUENCE'
);
-- 新部署对象
SELECT owner, object_name, created
FROM dba_objects
WHERE created > SYSDATE - 1
ORDER BY created DESC;
步骤5:系统资源分析
-- I/O性能
SELECT file_id, file_name,
ROUND((readtim*1000)/DECODE(readtim,0,1,reads)) avg_read_ms
FROM v$filestat
JOIN dba_data_files USING (file_id)
WHERE tablespace_name IN ('SYSTEM','SYSAUX');
-- 内存配置
SELECT pool, name,
ROUND(bytes/1024/1024) size_mb
FROM v$sgastat
WHERE name IN ('row cache','free memory');
步骤6:高级诊断
-- 追踪字典访问 (需Oracle Support)
ALTER SESSION SET events 'trace[row_cache] disk medium level 5';
-- 检查Bug
SELECT patch_id, description
FROM dba_registry_sqlpatch
WHERE patch_id IN (12902068, 21382587);
6. 根治方案
紧急处置
-- 预热字典缓存 (实例启动后)
EXEC DBMS_STATS.GATHER_DICTIONARY_STATS;
-- 固定核心对象
BEGIN
DBMS_SHARED_POOL.KEEP('SYS.STANDARD','P');
DBMS_SHARED_POOL.KEEP('SYS.DBMS_STANDARD','P');
END;
应用层优化
- 避免NOCACHE序列:
ALTER SEQUENCE order_seq CACHE 100; -- 原NOCACHE - 减少动态字典查询:
-- 原监控查询 SELECT * FROM dba_tables WHERE last_analyzed > SYSDATE-1; -- 改为物化视图 CREATE MATERIALIZED VIEW mv_table_stats REFRESH EVERY 60 MINUTES AS SELECT * FROM dba_tables; - 预加载对象:
-- 部署后立即编译 BEGIN FOR obj IN (SELECT object_name FROM user_objects) LOOP BEGIN EXECUTE IMMEDIATE 'ALTER '||obj.object_type||' '||obj.object_name||' COMPILE'; EXCEPTION WHEN OTHERS THEN NULL; END; END LOOP; END;
数据库调优
-- 共享池扩容
ALTER SYSTEM SET shared_pool_size=6G SCOPE=SPFILE;
-- 字典缓存调整 (11g+)
ALTER SYSTEM SET "_row_cache_cursors"=200 SCOPE=SPFILE; -- 默认50
-- 优化字典统计
EXEC DBMS_STATS.GATHER_DICTIONARY_STATS;
补丁与升级
- 关键补丁:
- Bug 12902068:应用11.2.0.4.210119+ PSU
- Bug 21382587:安装12.1.0.2.220719补丁
- 升级建议:
- 19c引入字典缓存自动优化
ALTER SYSTEM SET "_row_cache_auto_tuning"=TRUE; -- 默认开启
- 19c引入字典缓存自动优化
架构优化
- SSD存储:
将SYSTEM/SYSAUX表空间迁移至SSD - 备用库读分离:
将监控查询路由到物理备库 - 本地化字典:
-- RAC中设置服务亲和性 ALTER DATABASE SERVICE sales_service MODIFY PREFERENCE = 'sales_node';
根治原则:
解决row cache read= 减少物理I/O(预热缓存) + 优化内存配置 + 避免冷启动访问。
核心在于确保频繁访问的字典条目常驻内存,这对系统性能至关重要。
通过此方案可显著降低物理字典读取,提升数据库响应速度。
欢迎关注我的公众号《IT小Chen》
927

被折叠的 条评论
为什么被折叠?



