在线重定义停机仅发生在finish_redef_table瞬间,因需原子性rename表名并更新数据字典,实测通常为秒级;其余操作如数据同步、索引重建均在业务运行时异步完成。

在线重定义不能完全消除停机,但能把停机压缩到秒级——关键在 FINISH_REDEF_TABLE 那一瞬的独占锁。它不靠“不停机”吹牛,而是把耗时操作(数据同步、索引重建)全挪到业务运行时做,只留最后一步切换表名需要短暂锁定原表。真正在意停机时间的场景,比如金融核心账务表或电商订单主表,必须按这个逻辑设计节奏。
为什么 START_REDEF_TABLE 后业务还能读写原表
DBMS_REDEFINITION 底层用的是物化视图日志 + 快照复制机制,不是锁表拷贝。调用 START_REDEF_TABLE 后,Oracle 会自动在原表上建物化视图日志(如果不存在),后续所有 DML 变更都会被实时捕获并暂存。中间表(interim table)的数据同步是异步的,靠 SYNC_INTERIM_TABLE 主动触发,你完全可以每 10 分钟同步一次,业务全程无感。
常见错误现象:SYNC_INTERIM_TABLE 卡住不动?大概率是原表上有长事务未提交,或者物化视图日志堆积太多。别硬等,先查 v$mvlog 和 v$transaction。
使用场景:大表(>5000 万行)改造前,建议在低峰期执行首次 SYNC_INTERIM_TABLE,之后每小时同步一次,最后一次同步放在变更窗口前 5 分钟内完成。
FINISH_REDEF_TABLE 的停机到底多长
这一步本质是原子性 rename:把原表名指向新表段,再把旧表段标记为待清理。耗时与表大小无关,只取决于数据字典更新速度,实测通常
容易踩的坑:
- 没提前 kill 掉残留会话:执行前跑一遍
SELECT sid, serial#, sql_id, event FROM v$session WHERE blocking_session IS NOT NULL AND username = 'YOUR_SCHEMA' - 应用连接池里还挂着老事务:哪怕应用层已 commit,连接池可能复用旧连接并隐式开启新事务,建议变更前清空连接池
- 外键约束没处理干净:如果原表是子表且被其他表外键引用,
FINISH_REDEF_TABLE会失败,得先用COPY_TABLE_DEPENDENTS迁移约束
如何验证“停机真的只有几秒”
别信文档,要自己测。最直接的方式是在执行 FINISH_REDEF_TABLE 前后,用另一个会话持续轮询:
SELECT COUNT(*) FROM your_table WHERE ROWNUM = 1;
同时记录时间戳。你会看到:在 FINISH_REDEF_TABLE 执行期间,查询要么立刻返回结果,要么超时(说明锁住了),但绝不会卡住 30 秒以上。如果出现长时间阻塞,八成是上面提到的长事务或外键问题没扫干净。
性能影响注意点:整个过程对原表的 DML 性能有轻微影响(因为要维护物化视图日志),但读操作几乎无感知;中间表上的索引建议等 FINISH_REDEF_TABLE 完成后再建,避免拖慢同步速度。
真正难的不是命令怎么敲,而是判断哪几个事务必须杀、哪些依赖对象漏掉了、以及最后一次同步和切换之间有没有人偷偷发了一条 UPDATE。这些细节不盘清楚,秒级停机就变成小时级故障。











