START WITH/NEXT必须为DATE表达式而非字符串,否则ORA-12012错误导致job静默失败;ON COMMIT模式下该参数完全无效,仅ON DEMAND模式生效,且需确保job_queue_processes>0、非RESTRICTED SESSION,并验证USER_JOBS中FAILURES=0。
START WITH / NEXT 写法必须是 DATE 表达式,不是字符串
很多人直接写 start with 'sysdate + 1' 或 next 'trunc(sysdate) + 2/24',结果物化视图从不刷新,job 也查不到——因为 oracle 把这些当成了纯字符串字面量,导致 ora-12012 错误,job 启动就失败,但不报明显异常。
正确写法必须是可执行的 DATE 表达式:
-
START WITH SYSDATE(立即开始) -
NEXT TRUNC(SYSDATE) + 1 + 8/24(每天凌晨 8 点) -
NEXT TO_DATE(TO_CHAR(SYSDATE + 1, 'YYYY-MM-DD') || ' 02:00:00', 'YYYY-MM-DD HH24:MI:SS')(每天凌晨 2 点,兼容性更强)
别用 TO_DATE('2026-05-23', 'YYYY-MM-DD') 这类硬编码,NLS 设置一变就解析失败。验证是否生效:运行 SELECT NEXT FROM USER_MVIEWS WHERE MVIEW_NAME = 'YOUR_MV',返回值必须是可读日期,不能是空或乱码。
ON COMMIT 模式下 START WITH / NEXT 完全无效
如果你写了 REFRESH FAST ON COMMIT START WITH ... NEXT ...,Oracle 会安静地忽略 START WITH 和 NEXT —— 因为 ON COMMIT 刷新由事务提交触发,跟定时无关。
确认当前模式:
SELECT REFRESH_MODE, REFRESH_METHOD FROM USER_MVIEWS WHERE MVIEW_NAME = 'YOUR_MV'- 结果应为
DEMAND(不是COMMIT)
改用 ON DEMAND 后,还要检查:job_queue_processes 参数是否 > 0(Oracle 12c+ 建议设为 1000+),且数据库不能处于 RESTRICTED SESSION 状态,否则 job 根本不会启动。
DBMS_SCHEDULER 创建异步作业时,job_action 要转义单引号
用调度器创建异步刷新任务,常见错误是 job_action 中物化视图名没带 schema,或单引号没正确转义:
- 错误写法:
'BEGIN DBMS_MVIEW.REFRESH('DW.SALES_MV', 'F'); END;' - 正确写法:
'BEGIN DBMS_MVIEW.REFRESH(''DW.SALES_MV'', ''F''); END;'(内层单引号必须写成两个) - 物化视图名必须显式带上 schema,如
DW.SALES_MV,不能只写SALES_MV
作业默认以创建者身份运行;如果跨 schema 刷新,需提前授予 REFRESH ANY MATERIALIZED VIEW 权限。
刷新成功 ≠ 数据更新,FAILURES 字段才是关键
调度作业返回 “Job created” 或 JOB 显示 BROKEN = 'N',不代表数据真刷进去了。很多情况下 job 执行完了,但 DBMS_MVIEW.REFRESH 内部报错退出,错误被静默吞掉,只留下 FAILURES > 0 或 BROKEN = 'Y'。
必须查这个字段:
SELECT JOB, BROKEN, FAILURES FROM USER_JOBS WHERE WHAT LIKE '%DBMS_MVIEW.REFRESH%'-
FAILURES > 0→ 最近几次都失败了,不是“没跑”,而是“跑挂了” - 常见失败原因:
method => 'F'却没建物化视图日志、日志中SNAPTIME$$ = DATE '4000-01-01'(说明基表 DML 没提交)、没显式指定refresh_method导致走默认类型(可能是 ON COMMIT,但在作业里不生效)
大物化视图刷新建议加 ATOMIC_REFRESH => FALSE,否则可能因 undo 不足或超时中断;但要注意刷新过程中查询可能看到空或中间态。











