带复制触发器的Oracle表在线重定义方案咨询
解决方案:Oracle在线重定义中同步触发器的无丢失无重复处理
针对你遇到的DBMS_REDEFINITION重组带远程同步触发器表的问题,核心矛盾在于触发器激活时机导致的重复同步或数据丢失,可以通过严格控制触发器禁用/激活的时间窗口来解决,具体步骤如下:
完整操作流程
1. 初始化临时表与重定义
CREATE TABLE EMP_TMP AS SELECT * from EMP where ROWNUM=0; EXEC DBMS_REDEFINITION.START_REDEF_TABLE('SCOTT', 'EMP', 'EMP_TMP');
2. 复制索引、创建临时触发器(保持禁用)
注意临时表的触发器先不激活,避免同步重定义过程中的数据变更时产生重复记录:
-- 复制原表索引到临时表 CREATE INDEX IMP_I_TMP ON EMP_TMP ...; -- 创建与原触发器逻辑一致的临时触发器,但禁用 CREATE TRIGGER IMP_T_TMP BEFORE INSERT OR UPDATE OR DELETE ON EMP_TMP FOR EACH ROW BEGIN -- 原触发器中同步到远程应用的逻辑 END; ALTER TRIGGER IMP_T_TMP DISABLE;
3. 预同步减少数据差异(业务低峰期执行)
多次调用同步操作,缩小最后一次同步的数据量,降低后续锁表时间:
EXEC DBMS_REDEFINITION.SYNC_INTERIM_TABLE('SCOTT', 'EMP', 'EMP_TMP');
4. 核心操作(压缩时间窗口)
这一步要快速执行,尽量在业务低峰期操作:
-- 1. 禁用原表的同步触发器,避免原表后续操作触发远程同步 ALTER TRIGGER IMP_T DISABLE; -- 2. 同步最后一批变更到临时表,此时临时触发器禁用,不会产生重复同步 EXEC DBMS_REDEFINITION.SYNC_INTERIM_TABLE('SCOTT', 'EMP', 'EMP_TMP'); -- 3. 完成重定义,切换表名 EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE('SCOTT', 'EMP', 'EMP_TMP');
5. 切换对象名称并激活新触发器
-- 调整索引名称,对齐原表结构 ALTER TABLE EMP RENAME INDEX IMP_I TO IMP_I_OLD; ALTER TABLE EMP_TMP RENAME INDEX IMP_I_TMP TO IMP_I; -- 调整触发器名称 ALTER TRIGGER IMP_T RENAME TO IMP_T_OLD; ALTER TRIGGER IMP_T_TMP RENAME TO IMP_T; -- 激活新表的同步触发器,恢复远程同步逻辑 ALTER TRIGGER IMP_T ENABLE; -- 确认数据一致后,可清理旧对象 -- DROP TABLE EMP; -- DROP TRIGGER IMP_T_OLD;
为什么这个流程有效
- 避免重复同步:临时表触发器始终处于禁用状态,直到重定义完成后才激活,不会在重定义的同步阶段触发远程同步逻辑。
- 无数据丢失:禁用原表触发器后立即执行最后一次同步,确保原表的所有变更都通过
DBMS_REDEFINITION同步到临时表,重定义完成后激活新触发器,后续操作的同步逻辑正常运行。 - 业务影响极小:最后几步操作的时间窗口极短,配合业务低峰期执行,几乎不会影响正常业务。
内容的提问来源于stack exchange,提问作者darvud
相关产品推荐
相关产品推荐

