Oracle GoldenGate 11g 中实现 DDL 同步、双向复制(Bi-Directional Replication)和冲突解决机制

🧩 场景假设
项目 节点 A(源/主) 节点 B(目标/主)
主机名 primary1 primary2
IP 地址 192.168.1.10 192.168.1.11
数据库 SID ORCL ORCLD
OGG 安装路径 /u01/app/oracle/product/ggs11 相同
MGR 端口 7809 7809
用户 ggate ggate
✅ 实现目标:

双向 DML + DDL 复制
冲突检测与自动处理(如时间戳、序列号)
避免循环复制(使用过滤或标识)
🔷 第一步:启用 DDL 同步(必须两端都配置)

  1. 在数据库端安装 DDL 支持对象
    以 ggate 用户登录任一节点执行脚本(需先创建用户并授权):

-- 连接到数据库(ORCL 和 ORCLD 都要运行)
CONNECT ggate/ggate@ORCL

-- 执行 DDL 安装脚本(在 $GG_HOME 下)
@marker_setup.sql
-- 输入 Schema name for Marker: ggate

@ddl_setup.sql
-- 输入 GGS Owner: ggate
-- 输入 GGS User Password: ggate
-- Choose Yes to install into BOOTH tablespace

@role_setup.sql
-- 授权当前用户(ggate)GoldenGate 角色
GRANT GGS_GGSUSER_ROLE TO ggate;

@ddl_enable.sql
⚠️ 注意:

ddl_pin.sql 可选,用于性能优化(绑定到 SGA)
如果报错权限不足,请确认已执行 DBMS_GOLDENGATE_AUTH.GRANT_ADMIN_PRIVILEGE
2. 配置 Extract 参数支持 DDL 捕获(两端相同)
编辑抽取进程参数(例如 eora_1):

GGSCI> EDIT PARAM eora_1
添加以下内容:

EXTRACT eora_1
SETENV (ORACLE_SID = "orcl")
SETENV (ORACLE_HOME = "/u01/app/oracle/product/11.2.0/dbhome_1")
USERID ggate@orcl, PASSWORD ggate

EXTTRAIL ./dirdat/et

-- 启用 DDL 捕获
DDL INCLUDE ALL
DDLOPTIONS ADDTRANDATA, REPORT

TABLE scott.emp;
TABLE scott.dept;
📌 说明:

DDL INCLUDE ALL:捕获所有 DDL 操作(CREATE、ALTER、DROP 等)
DDLOPTIONS REPORT:将 DDL 写入报告文件便于调试
若只想捕获特定模式:DDL INCLUDE SCHEMA scott
3. 配置 Replicat 应用 DDL(目标端)
编辑 rora_1 参数:

GGSCI> EDIT PARAM rora_1
REPLICAT rora_1
SETENV (ORACLE_SID = "orcld")
SETENV (ORACLE_HOME = "/u01/app/oracle/product/11.2.0/dbhome_1")
USERID ggate@orcld, PASSWORD ggate

ASSUMETARGETDEFS

-- 启用 DDL 应用
DDL ERROR DEFAULT IGNORE RETRYOP
DDLOPTIONS SKIPERRORS

MAP scott.emp, TARGET scott.emp;
MAP scott.dept, TARGET scott.dept;
✅ 提示:可添加 TRACE LEVEL 调试 DDL 错误。

🔷 第二步:配置双向复制(Bidirectional Replication)
架构设计原则
为了避免“数据循环”问题(A→B→A→B…无限复制),必须使用如下策略之一:

方法 描述

  1. 使用环境变量标记来源(推荐) 设置 TRANLOGOPTIONS EXCLUDEUSER 或通过 FILTER 忽略来自 GG 的操作

  2. 使用触发器标记(不推荐,影响性能) 不建议在 OGG 中使用触发器

  3. 使用 HANDLECOLLISIONS + 过滤机制 结合事务标记
    我们采用最安全的方式:排除 OGG 用户的操作

  4. 在 Extract 中跳过由 GoldenGate 引起的变更
    修改两端的 Extract 参数(eora_1):

EXTRACT eora_1
...
-- 跳过由 ggate 用户产生的事务(防止回环)
TRANLOGOPTIONS EXCLUDEUSER ggate

EXTTRAIL ./dirdat/et
DDL INCLUDE ALL
...
✅ 原理:当 B 端的 Replicat 以 ggate 用户更新数据时,A 端的 Extract 会忽略该事务,避免再次发送回 B。

  1. 配置对称结构(两边都有 Extract + Pump + Replicat)
    节点 A(ORCL)上:
    Extract: eora_a → 捕获本地变更 → 发送到 B
    Replicat: rora_b ← 接收来自 B 的变更
    节点 B(ORCLD)上:
    Extract: eora_b → 捕获本地变更 → 发送到 A
    Replicat: rora_a ← 接收来自 A 的变更
    示例:节点 B 上的 Extract(eora_b)
    ADD EXTRACT eora_b, TRANLOG, BEGIN NOW
    ADD EXTTRAIL ./dirdat/eb, EXTRACT eora_b
    ADD EXTRACT pora_b, EXTTRAILSOURCE ./dirdat/eb
    ADD RMTTRAIL ./dirdat/ra, EXTRACT pora_b
    参数文件 eora_b.prm:

EXTRACT eora_b
SETENV (ORACLE_SID = "orcld")
SETENV (ORACLE_HOME = "/u01/app/oracle/product/11.2.0/dbhome_1")
USERID ggate@orcld, PASSWORD ggate

-- 关键:跳过自身应用的变更
TRANLOGOPTIONS EXCLUDEUSER ggate

EXTTRAIL ./dirdat/eb
DDL INCLUDE ALL

TABLE scott.emp;
TABLE scott.dept;
参数文件 pora_b.prm:

EXTRACT pora_b
RMTHOST primary1, MGRPORT 7809
RMTTRAIL ./dirdat/ra
PASSTHRU

TABLE scott.emp;
TABLE scott.dept;
节点 A 上新增 Replicat 接收来自 B 的数据(rora_b)
ADD REPLICAT rora_b, EXTTRAIL ./dirdat/ra
参数文件 rora_b.prm:

REPLICAT rora_b
SETENV (ORACLE_SID = "orcl")
SETENV (ORACLE_HOME = "/u01/app/oracle/product/11.2.0/dbhome_1")
USERID ggate@orcl, PASSWORD ggate

ASSUMETARGETDEFS

-- 启用 DDL
DDL ERROR DEFAULT IGNORE RETRYOP
DDLOPTIONS SKIPERRORS

-- 映射表
MAP scott.emp, TARGET scott.emp;
MAP scott.dept, TARGET scott.dept;
🔷 第三步:配置冲突检测与解决(Conflict Detection and Resolution, CDR)
在双向复制中,若两端同时修改同一行数据,就会发生冲突。OGG 提供了内置的 CDR 机制,基于时间戳或序列字段判断哪个更新更“新”。

✅ 前提:每张表必须有 时间戳字段 或 版本号字段

示例表结构增强
ALTER TABLE scott.emp ADD (
last_upd_ts TIMESTAMP DEFAULT SYSDATE NOT NULL,
source_node VARCHAR2(10) DEFAULT 'NODE_A' NOT NULL
);
last_upd_ts: 记录最后更新时间
source_node: 标识数据来源(用于解决冲突)
配置 Replicat 使用 CDR(以 rora_1 为例)
REPLICAT rora_1
...
-- 启用冲突检测
HANDLECOLLISIONS

-- 使用时间戳解决 UPDATE 冲突
MAP scott.emp, TARGET scott.emp,
COLMAP(USEDEFAULTS,
last_upd_ts = @GETENV("GGHEADER", "COMMITTIMESTAMP")),
FILTER(@COLTEST(last_upd_ts, GTE, @GETENV("GGHEADER", "COMMITTIMESTAMP")));

-- 如果是 INSERT,且主键已存在,则忽略
MAP scott.emp, TARGET scott.emp,
INSERTALLRECORDS,
RESOLVECONFLICT (
ON UPDATE OF last_upd_ts DO NOTHING,
ON INSERT DO NOTHING -- 或者更新其他字段
);
但这不是标准语法。OGG 11g 的 CDR 更依赖于 业务逻辑字段比较。

正确方式:使用 RESOLVECONFLICT + 时间戳字段
MAP scott.emp, TARGET scott.emp,
COLMAP(USEDEFAULTS,
last_upd_ts = @GETENV("GGHEADER", "COMMITTIMESTAMP")),
RESOLVECONFLICT (
ON DELETE DO NODELETE,
ON UPDATE OF last_upd_ts DO MAX,
ON INSERT DO PROCEED
);
📌 解释:

ON UPDATE OF last_upd_ts DO MAX:保留最新时间戳的数据
ON DELETE DO NODELETE:如果本地没有这条记录,不要删除(防误删)
ON INSERT DO PROCEED:插入继续执行(假设主键不会冲突)
❗ 主键冲突需靠应用层保证(如全局序列)

🔷 第四步:全局序列管理(避免主键冲突)
方案:使用奇偶序列或范围分配
方法一:节点 A 用奇数,节点 B 用偶数
-- 节点 A
CREATE SEQUENCE emp_seq START WITH 1 INCREMENT BY 2; -- 1,3,5...

-- 节点 B
CREATE SEQUENCE emp_seq START WITH 2 INCREMENT BY 2; -- 2,4,6...
方法二:使用 Sequence Routing(高级功能,需定制)
或者使用 Oracle Identity Column(12c+),但 OGG 11g 不支持。

🔷 第五步:启动与验证流程
启动顺序(两节点分别执行)
-- 启动管理进程
START MGR

-- 启动抽取和泵
START EXTRACT eora_1
START EXTRACT pora_1

-- 启动复制
START REPLICAT rora_1
START REPLICAT rora_b -- 接收对方数据
验证命令
INFO ALL
LAG REPICAT rora_1
VIEW REPORT eora_1
STATS EXTRACT eora_1 TOTALSONLY
测试场景
在 A 插入一行,检查 B 是否同步 ✅
在 B 修改同一行,检查 A 是否更新 ✅
同时在 A 和 B 修改同一行,查看谁保留(根据时间戳)✅
执行 ALTER TABLE ... ADD COLUMN,检查是否 DDL 同步 ✅
🔴 常见问题与解决方案
问题 原因 解决方法
DDL 报错 ORA-01031 权限不足 确保执行 ddl_setup.sql 和角色授权
循环复制(数据不停翻转) 未设置 EXCLUDEUSER ggate 添加 TRANLOGOPTIONS EXCLUDEUSER ggate
Replicat 因主键冲突 abort 两端同时插入相同主键 使用奇偶序列或 UUID
时间戳不同步导致冲突 系统时间不一致 使用 NTP 同步所有服务器时间
HANDLECOLLISIONS 导致数据丢失 配置不当 先测试再上线,开启 TRACE
✅ 最佳实践建议
禁止直接在数据库执行 DDL,应通过一个入口统一管理
所有表必须包含 last_update_timestamp 字段
使用独立网络通道传输 trail 文件
定期备份 checkpoint 文件
开启延迟监控告警
生产环境前充分测试冲突场景
📦 附件:完整参数模板下载(可保存为 .prm 文件)
👉 [点击此处生成模板打包文件](实际中可提供 ZIP)

✅ 总结
你现在已经掌握了如何在 Oracle GoldenGate 11g 上实现:

功能 是否完成 关键配置
✅ DDL 同步 ✔️ DDL INCLUDE, ddl_setup.sql
✅ 双向复制 ✔️ EXCLUDEUSER, 对称 Extract/Pump/Replicat
✅ 冲突解决 ✔️ RESOLVECONFLICT, 时间戳字段
✅ 主键防冲突 ✔️ 奇偶序列 / 范围分配
📌 下一步建议:

升级至 OGG 12c 或 19c,支持 Integrated Extract/Replicat 和更好的 CDR
使用 OGG Monitor 或 Prometheus + Exporter 实现可视化监控
配置 Heartbeat 表 检测复制延迟

posted @ 2026-02-09 14:23  wzusun  阅读(22)  评论(0)    收藏  举报