Result Cache对缓解shared pool latch争用基本无效,因其缓存查询结果而非SQL解析结构,不减少硬解析、不降低latch获取频率;且其元数据仍受shared pool latch保护,高并发下可能加剧争用。
为什么Result Cache对缓解shared pool latch争用基本无效
result cache缓存的是查询结果集,不是sql解析结构,它不减少硬解析、不降低library cache或shared pool latch的获取频率。启用result_cache_mode为force或在sql中加/*+ result_cache */,只会让后续相同sql跳过执行阶段——但前提是该sql已成功软解析甚至硬解析过。若sql本身因未绑定变量反复硬解析,result cache根本没机会生效,反而因额外维护cache metadata增加shared pool压力。
更关键的是:Result Cache对象本身也存于shared pool中,其元数据(如RC类型的heap)仍受shared pool latch保护。高并发读同一结果时,可能加剧latch争用而非缓解。
绑定变量是唯一真正有效的起点
shared pool latch争用高,90%以上根因是大量字面量SQL(literal SQL)导致硬解析暴增。Oracle必须为每条SELECT * FROM emp WHERE deptno = 1和SELECT * FROM emp WHERE deptno = 2分别分配内存、计算hash、插入链表——每次操作都要获取shared pool latch。
- 检查当前最“毒”的SQL:
SELECT substr(sql_text,1,40), COUNT(*) cnt FROM v$sqlarea WHERE FORCE_MATCHING_SIGNATURE != 0 GROUP BY substr(sql_text,1,40) HAVING COUNT(*) > 50 ORDER BY cnt DESC - 确认是否真未绑定:对疑似语句查
v$sql_shared_cursor,重点看UNBOUND_CURSOR、OPTIMIZER_MISMATCH、NLS_MISMATCH是否为Y - 应用层改造优先级:JDBC需禁用
implicitCache并显式复用PreparedStatement;Python cx_Oracle必须避免重复调用cursor.prepare(),而应prepare一次、execute多次
别碰CURSOR_SHARING=FORCE,尤其在19c
这个参数在19c中已明确标记为desupported(虽仍可用),且实际效果极不可控。它强制将字面量替换为系统生成的绑定变量,但无法保证执行计划一致性——比如WHERE status = 'A'和WHERE status = 'X'可能因数据分布差异触发不同索引路径,却被迫共享同一child cursor,最终引发ACS(Adaptive Cursor Sharing)抖动、子游标爆炸,反而拉长hash chain、加重latch竞争。
Oracle官方文档强调:CURSOR_SHARING应仅作为临时应急手段,长期方案必须由应用完成真实绑定。
容易被忽略的碎片化信号
即使硬解析已收敛,shared pool latch miss率仍高,大概率是碎片化所致。此时v$sgastat中free memory可能显示仍有几百MB,但request_misses持续上升——说明空闲块太小、太散,无法容纳新cursor的heap chunk。
不要刷shared pool,这会引发全局latch风暴;也不应盲目增大shared_pool_size,大pool会让hash查找变慢、加剧争用。正确做法是:观察v$librarycache中gethitratio是否低于0.99,再结合v$sqlarea中sharable_mem分布,定位是否被少数巨型SQL(如带大量注释或超长in-list的报表SQL)撑爆单个bucket。


















