atomic_refresh=TRUE导致刷新慢且锁表,因其强制单事务执行DELETE+INSERT,引发undo膨胀、长时表锁及ORA-01555;设为FALSE可启用TRUNCATE+分批INSERT,但需满足FAST刷新支持、日志完备及显式传参三前提。
atomic_refresh=TRUE为什么让刷新变慢又锁表
默认值 atomic_refresh => true 是绝大多数卡顿、锁表、ora-01555 的根源。它强制整个刷新走单事务:delete 所有旧数据 → insert 所有新数据 → commit。百万级物化视图下,这等于把所有 dml 压进一个事务里。
常见表现包括:
-
v$session中长期卡在enq: TX - row lock contention或db file sequential read -
v$locked_object显示物化视图基表或MLOG$_xxx表被锁,locked_mode为 6(EXCLUSIVE) - 刷新耗时随数据量线性增长,且无法通过
parallelism加速
根本问题不是“慢”,而是事务粒度太大——undo 段撑爆、redo 写满、行锁堆积,业务 DML 一碰就阻塞。
atomic_refresh=FALSE真生效的三个前提
设成 FALSE 不等于自动变快。它只在满足以下条件时才真正启用 TRUNCATE+INSERT 或分批提交模式:
- 物化视图必须支持 FAST 刷新:
SELECT fast_refreshable FROM user_mviews WHERE mview_name = 'YOUR_MV'返回FAST,不能是DIRLOADDML或UNDEFINED - 物化视图日志结构完整:
SELECT ROWIDS, PRIMARY_KEY, SEQUENCE FROM user_mview_logs WHERE master = 'YOUR_TABLE'至少两个字段为YES - 调用时显式传参,不能依赖默认值:
DBMS_MVIEW.REFRESH('MV_NAME', atomic_refresh => FALSE)—— 封装在 JOB 或存储过程里也必须硬编码该参数
缺任一条件,Oracle 会静默退化为 COMPLETE 刷新,反而更慢、更锁。
并行刷新不生效?先查 atomic_refresh 是否配对
设了 parallelism => 4 却只看到 1 个 PX 进程,大概率是 atomic_refresh 还在 TRUE。并行机制只在 FALSE 下激活,因为只有这时才能分批次提交(如每 5 万行 commit 一次),多个 PX 进程才真正独立工作。
验证是否生效:
- 刷新中查
v$px_session:应看到多个活跃 PX 进程 - 查
v$transaction:多个不同addr的事务,而非单个长事务 - 用
DBMS_XPLAN.DISPLAY_CURSOR('sql_id')看执行计划:出现TRUNCATE TABLE或多段INSERT /*+ APPEND */才算到位
单独设 parallelism 而不改 atomic_refresh,就像给四个人发一把钥匙——他们只能排队开门。
业务能否容忍刷新中间态
atomic_refresh => FALSE 的代价很实在:刷新窗口内查询可能返回空表、部分新数据、或新旧混合结果。这不是 bug,是明确的设计行为。
如果应用要求“始终可查且数据一致”,这个参数就不能开;得换方案,比如分区交换(EXCHANGE PARTITION)或双 MV 轮换。强行保“不断供”而不开 FALSE,等于选择用锁和超时换一致性。
最容易被忽略的是:哪怕开了 FALSE,若基表本身存在主键冲突或脏数据,INSERT 阶段会直接报 ORA-00001,且已提交批次无法回滚——所以刷新前务必校验源数据质量。



















