会锁表,且是分钟级甚至小时级的排他锁;MOVE后索引失效因未重建,需加UPDATE INDEXES或显式REBUILD;LOB段不随分区自动迁移,须逐列声明;统计信息丢失导致执行计划恶化,须手动收集。
ALTER TABLE MOVE PARTITION 会锁表吗?
会,而且是排他锁(exclusive lock),整个分区在迁移过程中不可读写,持续到操作完成——不是“瞬间锁”,而是分钟级甚至小时级阻塞。大分区迁移时,应用端常出现 ora-00054: resource busy and acquire with nowait specified 或连接堆积、sql 超时。
常见误判是以为加了 POLICY 或并行就能“不锁”,但 Oracle 的 MOVE PARTITION 本质是重建段,必须独占访问。低峰期执行是硬性要求,不能靠“试试看”。
- 即使表启用了
ROW MOVEMENT,也不缓解锁问题 -
DBMS_REDEFINITION可在线迁移,但要额外空间、双倍维护成本,冷热分层场景通常没必要 - 若业务完全无法停写,只能切到备库做迁移再切换,而非在主库硬扛
MOVE PARTITION 后索引为什么失效?
因为 MOVE PARTITION 只动数据段,不碰索引结构。全局索引直接变 UNUSABLE,局部索引分区对应的数据段变了,但索引分区本身没重建,状态可能仍为 USABLE,但指向的 rowid 已无效。
查询走全表扫描、执行计划突变、性能暴跌,八成是因为这个。
- 加
UPDATE INDEXES参数可自动重建所有相关索引(含全局和局部),但仅重建结构,不收集统计信息 - 若不想重建全部索引,改用显式重建:
ALTER INDEX idx_name REBUILD(全局)或ALTER INDEX idx_name REBUILD PARTITION p_name(局部) - 带子分区的表,必须用
SUBPARTITION关键字,写成PARTITION会报错
LOB 字段怎么一起迁?漏掉就白干
LOB 段默认不随分区移动,仍留在原表空间。表面看 MOVE PARTITION 成功了,实际 DBA_SEGMENTS 里还能查到旧表空间里的 LOB 段,后续归档或收缩表空间会失败。
必须显式声明 LOB 存储位置,且每个 LOB 列都要单独写。
- 语法是:
LOB (col_name) STORE AS (TABLESPACE tbs_new) - 多个 LOB 列要重复写多次:
LOB (c1) STORE AS (...), LOB (c2) STORE AS (...) - 如果列名拼错、类型不匹配(比如把
CLOB当成普通字段忽略),命令能执行成功,但 LOB 段不动 - 迁移后建议查:
SELECT segment_name, tablespace_name FROM dba_segments WHERE segment_type = 'LOBSEGMENT' AND owner = 'YOUR_SCHEMA'
统计信息丢失导致执行计划恶化
MOVE 完分区,DBA_TAB_STATISTICS 里该分区的 NUM_ROWS 变成 NULL 或极小值,优化器估算严重失真:分区裁剪失效、本该走索引却选了全表扫描、绑定变量窥探结果错乱。
这不是 bug,是设计如此——MOVE 是物理操作,不触发统计信息自动刷新。
- 立刻执行:
DBMS_STATS.GATHER_TABLE_STATS(ownname => 'OWNER', tabname => 'TBL_NAME', partname => 'P_NAME', granularity => 'PARTITION') - 别依赖
UPDATE INDEXES带来的“顺手更新”,它只管索引结构 - 如果表有增量统计信息(incremental stats),记得同步更新全局统计信息,否则分区级准确但整体不准
MOVE PARTITION 最容易被忽略的,其实是 LOB 子句的逐列声明和统计信息的手动收集——这两步不补,迁移后的问题不会立刻报错,而是在某次高峰查询时突然爆发。











