物化视图无法自动刷新,是因为数据库本身不提供开箱即用的自动机制;Oracle的START WITH/NEXT仅标记时间,依赖job_queue_processes>0、ON DEMAND模式及有效DBA_JOBS任务,PostgreSQL需pg_cron或系统cron,MySQL则完全靠模拟。

物化视图无法自动刷新,是因为它根本就不是“自动”的东西——所有主流数据库(Oracle、PostgreSQL、MySQL)都不提供开箱即用的自动刷新机制,所谓“定时”或“实时”,全靠外部驱动。
Oracle 的 START WITH / NEXT 只是标记,不是定时器
很多人以为在 CREATE MATERIALIZED VIEW 里写了 NEXT TRUNC(SYSDATE)+1 就能每天刷一次,其实这只是告诉 Oracle “下次该算时间了”,真正干活的后台 job 必须存在且可运行。常见卡点包括:
-
job_queue_processes = 0(12c+ 建议设为 1000,否则 job 队列被禁用) - 物化视图刷新模式是
ON COMMIT,此时START WITH/NEXT完全被忽略 - 数据库处于
RESTRICTED SESSION模式,job 被跳过不执行 -
DBA_JOBS里查不到对应记录,说明创建时 job 注册失败(比如权限不足或语法错)
PostgreSQL 根本没有内置调度,CONCURRENTLY 不等于增量
REFRESH MATERIALIZED VIEW CONCURRENTLY 听起来像“边刷边用”,但它仍是全量重跑原始查询,只是靠唯一索引做 upsert 合并,不锁表而已。它不监听源表变更,也不读 WAL 日志。生产中必须配外部调度:
- 装
pg_cron:需shared_preload_libraries = 'pg_cron'+ 重启,且调用用户要有USAGE ON SCHEMA cron - 系统
cron调psql -c "REFRESH MATERIALIZED VIEW CONCURRENTLY mv_name":注意-U、-d和连接池超时设置 - 漏建唯一索引?直接报
ERROR: cannot refresh materialized view "mv_xxx" concurrently because it does not have a unique index
MySQL 压根没物化视图语法,只能模拟
MySQL 8.0 仍不支持 MATERIALIZED VIEW 关键字。所谓“定时刷新”,本质是人工维护一张普通表 + 外部调度:
- 建表结构匹配源逻辑(如
sales_summary_mv),用INSERT SELECT初始化 - 用
EVENT(需event_scheduler=ON)或crontab定时执行TRUNCATE + INSERT SELECT - 若用
INSERT ... ON DUPLICATE KEY UPDATE替代全量刷,得确保源表有稳定唯一键,且触发逻辑覆盖所有 DML 类型(INSERT/UPDATE/DELETE)
最常被忽略的一点:你看到的“没刷新”,往往不是调度没跑,而是刷新本身失败了却没暴露错误——比如 Oracle 的 ORA-12008 是占位符,背后可能是空间不足或权限缺失;PostgreSQL 的 CONCURRENTLY 刷一半失败,可能已部分写入导致数据重复。不查日志、不验状态,只改调度时间,问题永远在原地。


















