能实现增量同步,但必须依赖可追踪的变更字段(如时间戳或自增主键),merge仅处理新增和修改,删除需单独执行delete语句补全。
能,但必须依赖可追踪的变更字段(如时间戳或自增主键),且不能只靠 merge 一把梭——它不处理源端已删除的记录。
增量同步必须有可靠的变更标记字段
没有 LAST_MODIFIED、UPDATE_TIME 或单调递增的 ID 字段,就无法界定“哪些是新/改数据”。硬写 SYSDATE - 1/24 这类窗口会漏数据:作业延迟 2 小时,那中间的变更就丢了。
- 若源表无变更字段,先执行
ALTER TABLE source_tab ADD (update_time DATE DEFAULT SYSDATE),再用UPDATE source_tab SET update_time = created_time WHERE update_time IS NULL补历史值 - 字段类型优先选
TIMESTAMP,避免跨时区或夏令时导致的比较偏差 - 测试时用
SELECT MAX(update_time) FROM source_tab确认该字段真正在业务中被更新
MERGE INTO 只解决增和改,删必须单独处理
MERGE 本质是“源驱动”,只能插入或更新目标表中匹配的行,对源表已删除、但目标表仍存在的“孤儿数据”完全无感。生产环境必须补上删除逻辑。
- 先跑
MERGE同步新增/修改:MERGE INTO target t USING (SELECT id, name, status, update_time FROM source WHERE update_time > v_last_sync_time) s ON (t.id = s.id) WHEN MATCHED THEN UPDATE SET t.name = s.name, t.status = s.status, t.update_time = s.update_time WHEN NOT MATCHED THEN INSERT (id, name, status, update_time) VALUES (s.id, s.name, s.status, s.update_time); - 再执行删除:
DELETE FROM target WHERE id NOT IN (SELECT id FROM source WHERE update_time > v_last_sync_time) AND update_time —— 注意加 <code>update_time 条件,防止误删刚同步进来的新记录</code>
- 三步必须包在同一个事务里,任一失败则
ROLLBACK
同步状态必须持久化到本地表,不能靠变量或临时存储
定时任务(如 DBMS_SCHEDULER)每次以新会话运行,局部变量 v_last_sync_time 无法跨次传递。断点续传全靠一张控制表。
- 建表示例:
CREATE TABLE sync_control ( table_name VARCHAR2(30) PRIMARY KEY, last_sync_time TIMESTAMP, last_handle_time TIMESTAMP );
- 存储过程开头查:
SELECT last_sync_time INTO v_last_time FROM sync_control WHERE table_name = 'SOURCE_TAB'; - 成功执行后更新:
UPDATE sync_control SET last_sync_time = v_current_time, last_handle_time = SYSTIMESTAMP WHERE table_name = 'SOURCE_TAB'; - 务必在
EXCEPTION块里写日志(如插入sync_log表),否则失败无声,没人知道停在哪了
最易被忽略的是权限与 DBLINK 的 PUBLIC 属性——非 PUBLIC 的 DBLINK 在 DBMS_SCHEDULER 作业里直接报 ORA-02019: connection description for remote database not found;而密码没加双引号,在 Oracle 12c+ 上必触发 ORA-01017,哪怕账号密码一字不差。











