Oracle 19c RAC中同一SQL在不同节点执行计划不同的最常被忽略根源是会话级或实例级参数不一致,即使spfile共享,optimizer_mode等参数仍可能因sid限定导致实际值不同,需通过v$system_parameter2和gv$ses_optimizer_env逐层排查。
检查各实例初始化参数是否同步
oracle 19c rac 中同一 sql 在不同节点生成不同执行计划,**最常被忽略的根源之一就是会话级或实例级参数不一致**。即使 spfile 是共享的,某些参数仍可能被显式设为 sid='node1' 或 sid='node2',导致两个实例实际生效值不同。
典型影响参数包括:optimizer_mode、optimizer_index_cost_adj、parallel_degree_policy、cursor_sharing、db_file_multiblock_read_count。这些参数直接参与成本计算,微小差异就足以让优化器在索引扫描 vs 全表扫描、并行 vs 串行之间做出不同选择。
- 用
SHOW PARAMETER查当前会话值,但更关键的是查实际生效的实例级配置:SELECT name, value, issid, ispdb_modifiable FROM v$parameter WHERE name IN ('optimizer_mode','optimizer_index_cost_adj','parallel_degree_policy') ORDER BY name; - 重点看
issid列:若为TRUE,说明该参数支持按实例覆盖;再查v$system_parameter2确认每个实例的实际值:SELECT inst_id, name, value FROM gv$system_parameter2 WHERE name IN ('optimizer_mode') ORDER BY inst_id, name; - 不要只信
spfile内容——用CREATE PFILE FROM SPFILE导出后人工比对各SID.段落,确认没有残留的node1.optimizer_mode='FIRST_ROWS'这类隐式覆盖 - 注意
ALTER SYSTEM SET ... SCOPE=BOTH默认作用于所有实例,但加了SID='node1'就只改单边;回滚时也必须指定相同SID,否则残留差异会持续存在
为什么参数同步了还出问题?关注隐式会话级覆盖
即使 v$system_parameter2 显示两节点参数完全一致,仍可能因应用连接时携带了会话级设置而触发差异。比如 JDBC 连接字符串里带 oracle.jdbc.defaultRowPrefetch=100,虽不直接影响执行计划,但若搭配 optimizer_mode=FIRST_ROWS,会进一步强化优化器对“快速返回前几行”的倾向,间接改变索引选择逻辑。
- 检查应用连接是否显式执行了
ALTER SESSION:查gv$sql中对应 SQL 的sql_text是否包含ALTER SESSION SET optimizer_mode类语句 - 用
gv$session看问题 SQL 所属会话的参数快照:SELECT s.inst_id, s.sid, p.name, p.value FROM gv$session s JOIN gv$ses_optimizer_env p ON (s.sid = p.sid AND s.inst_id = p.inst_id) WHERE s.sql_id = 'your_sql_id' AND p.name IN ('optimizer_mode','optimizer_index_cost_adj'); - 特别警惕
cursor_sharing=FORCE+ 绑定变量场景:不同节点上绑定变量窥探(bind peeking)发生的时机可能因硬解析顺序不同而错开,导致首次生成计划时看到的值不同
验证参数影响的最小闭环操作
别依赖 AWR 报告里模糊的“执行计划哈希值不同”结论。要快速验证是否是参数导致,必须在相同会话上下文中强制复现。
- 在节点1上,用
sqlplus / as sysdba连接后,先查当前参数:SHOW PARAMETER optimizer_mode - 再手动 set 成节点2的值:
ALTER SESSION SET optimizer_mode=ALL_ROWS; - 立刻执行原 SQL 并
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);看是否 Plan Hash Value 变成和节点2一致 - 反向操作(节点2上 set 成节点1的值)验证可逆性;如果 Plan Hash 值随之切换,基本可锁定是该参数差异所致
真正容易被忽略的点在于:RAC 中参数同步不是“设一次就万事大吉”,而是每次 ALTER SYSTEM 都得核对 inst_id 范围,且应用层的会话级覆盖会绕过所有实例级配置。不抓到具体哪个参数、哪个会话、哪次解析在作祟,光看 AWR 或 gv$parameter 列表永远只能猜。


















