ALTER TABLE … MERGE PARTITIONS 是物理重写操作,会持排他锁、阻塞DML、重写ROWID并破坏物化视图日志稳定性,需手动验证LIST值、重建MV日志、收缩空间及收集统计信息。

ALTER TABLE … MERGE PARTITIONS 会锁表且重写数据
这不是元数据操作,而是物理移动:Oracle 把两个分区所有行读出、按新分区键重新计算位置、写入新段。整个过程持有 EXCLUSIVE DML 锁,期间任何 INSERT/UPDATE/DELETE 都会被阻塞。大表(比如千万行以上)可能卡住数小时,I/O 和 redo 压力陡增。
实操建议:
- 提前查数据量:
SELECT num_rows, blocks FROM user_tab_partitions WHERE table_name = 'T' AND partition_name IN ('P1','P2') - 确认目标表空间空闲空间 ≥ 两分区之和,否则直接报
ORA-01653 - 别在事务里混用 MERGE 和 DML —— 未提交的 MERGE 不产生日志,后续物化视图刷新会断链
- 避免在 NOLOGGING 表上强行加
NOLOGGING子句,MERGE PARTITIONS本身不支持该语法,加了就报ORA-14049
LIST 分区合并后 VALUES IN 必须手动补全,漏值直接导致 INSERT 失败
Oracle 不自动合并、去重或排序 LIST 值列表。如果原分区 P1 VALUES IN ('A','B') 和 P2 VALUES IN ('C') 合并为 P12,但语句只写 VALUES IN ('A','C'),那插入 'B' 就立刻报 ORA-14400。
验证方式:
- 执行前查清楚原始值:
SELECT partition_name, high_value FROM user_tab_partitions WHERE table_name = 'T',注意HIGH_VALUE是表达式,需用DBMS_METADATA.GET_DDL或TO_LOB解析 - 合并后立刻测试插入所有原值:
INSERT INTO t (col) VALUES ('A'),('B'),('C') - DEFAULT 分区不可参与 MERGE,否则报
ORA-14080
合并后物化视图 FAST 刷新失效,必须重建日志 + COMPLETE 刷新
MERGE PARTITIONS 会重写 ROWID、破坏物化视图日志(mlog$)稳定性,导致后续 REFRESH FAST 报 ORA-12008 或 ORA-12012。根本原因是日志依赖 ROWID 稳定性,而 MERGE 不触发日志更新逻辑。
修复步骤:
- 先
DROP MATERIALIZED VIEW LOG ON your_table(若原日志含PRIMARY KEY,不能直接叠加ROWID) - 再重建日志:
CREATE MATERIALIZED VIEW LOG ON your_table WITH ROWID, SEQUENCE (id, event_time) INCLUDING NEW VALUES - 必须立即执行
REFRESH COMPLETE,否则USER_MVIEWS.STALENESS变成UNUSABLE,FAST 能力无法恢复 - 若物化视图含跨分区聚合(如
GROUP BY TRUNC(date_col, 'MM')),日志缺INCLUDING NEW VALUES仍会拒绝 FAST
亿级分区表合并后必须 SHRINK SPACE + 重收集统计信息
MERGE 操作不自动清理高水位线(HWM),旧分区碎片残留,NUM_ROWS / BLOCKS 比值持续低于 5 就说明严重碎片化。查询响应变慢、执行计划失真都可能由此引发,但不会报错,容易被忽略。
关键动作:
- 合并完成后立刻执行:
ALTER TABLE t_part MODIFY PARTITION p12 SHRINK SPACE - 接着收集统计信息:
DBMS_STATS.GATHER_TABLE_STATS('SCHEMA', 'T_PART', GRANULARITY => 'PARTITION') - 检查
USER_TAB_STATISTICS中STALE_STATS = 'NO'且NUM_ROWS合理 - 别等默认维护任务,用
DBMS_PART.CLEANUP_GIDX('SCHEMA', 'T_PART')主动清理全局索引孤儿条目
STALENESS 状态、没人看 NUM_ROWS/BLOCKS 比值、没人验证 LIST 值是否全覆盖——这些点不手动确认,数据就处于“看似正常、实际脆弱”的状态。


















