physical reads高本质是内存未被有效利用,而非os缺内存;其主因包括buffer cache命中失败、人为清空cache、大表扫描挤出热块、绑定变量窥探失效致执行计划漂移,需结合v$librarycache等视图验证db_cache_size配置是否失当。

物理内存充足但AWR报告中出现高Paging(即v$sysstat里physical reads或physical writes异常高,或DB Time中I/O等待占比突增),本质不是“内存不够”,而是“内存没被有效利用”——Oracle把该缓存的数据漏掉了,或缓存结构被干扰了。
为什么physical reads高不等于OS缺内存
AWR里的physical reads统计来自v$sysstat,它只反映Oracle进程向OS发起的块级读请求次数,和Linux/Unix的pgpgin/pgpgout(页换入换出)无直接对应关系。常见误解是:看到physical reads飙升就去查free -h,结果发现Mem free还有20GB——这完全不矛盾。
-
physical reads高,说明buffer cache命中失败(Buffer Hit %db_cache_size里,必须从磁盘读 - OS层面内存充足,只说明没触发OOM Killer或swap out,但Oracle的SGA/PGA是否真被OS稳定驻留,取决于
vm.swappiness、memlock限制、以及是否启用USE_LARGE_PAGES=TRUE - 若
sga_max_size>/proc/sys/vm/max_map_count,Oracle可能降级使用小页,导致TLB miss升高,间接加剧逻辑读转物理读
Buffer Hit %低的三大隐藏原因
别只看AWR顶部的“Buffer Hit %”数字。这个值掩盖了访问模式差异——全表扫描(FTS)天然拉低命中率,但未必是问题;真正要揪的是“本该命中却没命中”的场景。
- 频繁
ALTER SYSTEM FLUSH BUFFER_CACHE或DBMS_SHARED_POOL.PURGE:人为清空cache,且未被记录在AWR的“Other”等待里 - 大表全扫描后未及时老化:当
db_cache_size不足容纳热数据+扫描临时块时,后续索引访问块被挤出,造成二次物理读 - 绑定变量窥探(bind peeking)失效导致执行计划漂移:某次硬解析用了
INDEX RANGE SCAN,下次却因统计信息陈旧走了FULL TABLE SCAN,AWR里Executions数不变,但Physical Reads翻倍
如何确认是不是db_cache_size配置失当
不能只比对show parameter db_cache_size和物理内存。关键看实际利用率与争用信号:
- 查
v$librarycache:若gethitratiopinhitratio - 看AWR中“Instance Efficiency Percentages”部分:
Execute to Parse %若 - 运行
SELECT * FROM v$sgastat WHERE name IN ('free memory', 'db_block_buffers'):若free memory长期
容易被忽略的OS层干扰点
Oracle进程的内存页是否真能锁住,取决于内核配置,而非数据库参数本身:
- 检查
ulimit -l:若返回unlimited,再确认/etc/security/limits.conf中oracle soft memlock和hard memlock是否设为unlimited或≥SGA大小(单位KB) - 确认
vm.nr_hugepages已预分配且被Oracle识别:grep -i huge /proc/meminfo应显示HugePages_Free> 0;否则即使设了use_large_pages=only,实例启动也会静默退回到small pages - Linux 4.12+内核默认启用
THP(Transparent Huge Pages),但Oracle官方明确不推荐——它会导致周期性khugepaged扫描引发latch: cache buffers chains争用,表现为AWR中DB CPU虚高而physical reads同步上升
最常被跳过的动作:查v$sga_dynamic_components里current_size是否稳定。如果DEFAULT buffer cache的值在快照间波动超过10%,说明自动内存管理(AMM)正在和OS内存回收博弈,此时停用memory_target、改用手动sga_target+pga_aggregate_target才是治本之策。











