QUERY_REWRITE_ENABLED会话级参数被连接池重置,需在连接池初始化语句中显式设置ALTER SESSION;QUERY_REWRITE_INTEGRITY=ENFORCED导致静默失败,应调为TRUSTED验证;QUERY REWRITE权限必须直授且跨schema需GLOBAL权限;MV必须建时指定ENABLE QUERY REWRITE,否则无效。
QUERY_REWRITE_ENABLED 会话级被连接池重置
生产环境几乎都用连接池(druid、ucp、hikaricp),而 oracle 默认会话参数 query_rewrite_enabled 是 false。即使你改了实例级参数为 true,连接一建立,会话仍继承默认值。
验证方法:在应用执行 SQL 前,连上同一批连接,运行:SELECT SYS_CONTEXT('USERENV', 'SESSIONID') FROM DUAL;,再查 V$SES_OPTIMIZER_ENV 中 query_rewrite_enabled 的值——不是看 V$PARAMETER,那只是实例级。
- 修复方式:在连接池初始化语句中加入
ALTER SESSION SET QUERY_REWRITE_ENABLED = TRUE - 若用 UCP,需配置
connectionPool.setConnectionFactoryProperty("initSql", "ALTER SESSION SET QUERY_REWRITE_ENABLED = TRUE") - 别依赖
/*+ REWRITE */hint——它不强制生效,只在重写路径已就绪时起作用
QUERY_REWRITE_INTEGRITY=ENFORCED 卡住重写尝试
这是最隐蔽的“静默失败”原因。默认值 ENFORCED 不是“不重写”,而是“发现一点不合规就跳过,连日志都不记”。哪怕 MV 是 FRESH、语法完全匹配,只要基表缺物化视图日志、或约束没 VALIDATED,优化器就直接放弃。
典型报错不会明说,但 DBMS_MVIEW.EXPLAIN_REWRITE 输出里会出现:QSM-01150: no suitable materialized view found 或 materialized view is stale(注意:此时 DBA_MVIEWS.STALENESS 可能仍是 FRESH,因为校验发生在更底层)
- 快速验证:临时执行
ALTER SESSION SET QUERY_REWRITE_INTEGRITY = TRUSTED,再跑EXPLAIN PLAN—— 若执行计划切到 MV,说明就是它卡住 - 生产慎用
STALE_TOLERATED:它允许用STALEMV,但报表结果可能脏读 - 真正修复要补基表日志:
CREATE MATERIALIZED VIEW LOG ON sales WITH ROWID, SEQUENCE (region, amount, order_date) INCLUDING NEW VALUES,漏列或缺INCLUDING NEW VALUES都不行
QUERY REWRITE 权限无法通过角色继承
哪怕用户在 SESSION_ROLES 里看到 DBA,QUERY REWRITE 权限也不会生效。Oracle 明确要求该权限必须直授用户,且跨 schema 还要额外加 GLOBAL QUERY REWRITE。
常见误判:用 SELECT_CATALOG_ROLE 代替 SELECT 权限。这个角色能查数据字典,但不能访问别人建的物化视图物理表。
- 必须执行:
GRANT QUERY REWRITE TO app_user(不能通过角色) - 若 MV 在
reportingschema,查询在appschema:GRANT GLOBAL QUERY REWRITE TO app_user+GRANT SELECT ON reporting.mv_sales_sum TO app_user - 检查权限是否生效:
SELECT * FROM SESSION_PRIVS WHERE PRIVILEGE = 'QUERY REWRITE'—— 这个视图才反映真实授权
物化视图定义漏掉 ENABLE QUERY REWRITE 子句
建 MV 时只写 CREATE MATERIALIZED VIEW mv AS SELECT ...,没加 ENABLE QUERY REWRITE,那它就是一个普通表。优化器根本不会把它放进重写候选列表,EXPLAIN PLAN 里自然看不到它。
已有 MV 不能用 ALTER MATERIALIZED VIEW ... ENABLE QUERY REWRITE 补——语法不支持。很多人试了报 ORA-30372: illegal operation on a materialized view 就卡住。
- 唯一办法:
DROP MATERIALIZED VIEW mv_sales_sum后重建,末尾明确加上ENABLE QUERY REWRITE - 注意兼容性:
ENABLE QUERY REWRITE要求基表有主键或启用ROWID,否则建 MV 会报ORA-30353 - 别信“hint 能救场”:
/*+ REWRITE(mv_sales_sum) */在 MV 本身不支持重写时,会被优化器直接忽略
实际排查时,DBMS_MVIEW.EXPLAIN_REWRITE 的输出比 EXPLAIN PLAN 更关键——后者只告诉你“最终选了谁”,前者才告诉你“为什么没选它”。而所有这些配置项,任何一个没对齐,重写就彻底失效,Oracle 不会降级尝试。


















