OGG单向DDL复制实战:Oracle GoldenGate结构变更同步配置全解析

发布时间:2026/10/13 11:07:03
OGG单向DDL复制实战:Oracle GoldenGate结构变更同步配置全解析
上个月给某客户搭了一套OGG数据库复制环境核心需求非常明确把源生产库某个业务用户下的结构变更DDL自动同步到目标分析库。这条链路不传DML数据只传DDL做单向复制。简单说就是源库有人建了表、改了字段、删了对象目标库要自动跟着做同样的动作不用人工再跑一遍脚本。整个配置过程踩了不少坑从DDL支持脚本安装、权限模型设计到抽取进程和复制进程的参数组合再到实际验证时暴露出的各种问题前后折腾了快两天。这篇把完整过程复盘一遍重点讲清楚每一步为什么这么做、参数怎么选、哪些地方容易栽跟头希望对正在做OGG DDL单项复制的朋友有帮助。1. 场景与方案选型为什么需要DDL单项复制1.1 项目背景还原客户环境里有两个Oracle数据库生产库P和数据分析库D。生产库P跑核心业务数据仓库团队需要定期从P库拉数据到D库做分析。原本数据导入靠ETL定时任务但最近业务侧频繁调整表结构今天加字段明天改字段长度后天又新建表ETL每次都要手动去D库同步结构经常因为漏改导致任务失败。所以他们提出的需求是把P库某个业务用户就叫app_schema下的所有DDL操作自动、实时同步到D库对应用户下。这样结构永远保持一致ETL只需要关心数据不用再管结构差异。这种场景在业务快速迭代、报表需求多变的环境中非常典型。1.2 为什么选OGG而不是其他方案当时团队也评估过几个替代方案。数据库自带方案方面Data Guard逻辑备库能做结构同步但那是整个库级别的复制会带来额外负载而且配置复杂不适合只同步特定schema的业务。触发器方案方面可以在Oracle里用AFTER DDL触发器捕获DDL再通过DBLINK在目标库执行这个思路看着简单但有一个致命问题DDL触发器触发时事务还没提交在触发器里远程执行DDL很容易因为分布式事务时序问题出错而且对源库侵入性很强。相比之下Oracle GoldenGate简称OGG是专门做异构或同构数据库实时复制的工具基于日志解析天然支持DDL和DML统一抓取对源库几乎没有侵入性。最关键的是OGG拥有完善的事务边界处理能力能保证DDL和同一会话内的DML按正确顺序同步到目标端。综合考虑后OGG是最合适的选择。1.3 DDL复制与DML复制的本质区别OGG的核心原理是读取在线重做日志和归档日志把源库变更解析成逻辑记录经过trail文件传输到目标端再由目标端进程重放。DML复制捕获的是INSERT、UPDATE、DELETE这些数据变更每一条记录对应一行数据的逻辑变化。DDL复制捕获的是CREATE、ALTER、DROP、TRUNCATE这类结构变更解析逻辑要复杂得多因为DDL在redo log中记录的上下文信息非常有限。OGG必须额外在源库安装一套DDL支持对象包括内部日志表、触发器和辅助包专门负责把DDL信息补全后写入日志表抽取进程再从这张表抓取DDL语句。这个区别非常关键。很多人以为OGG装好就能直接抓DDL实际上不安装DDL支持脚本EXTRACT进程根本拿不到DDL数据。我这次配置踩的第一个大坑就在这一步。2. 配置前的准备版本、权限与安装DDL支持脚本2.1 源端和目标端环境客户环境的具体版本信息如下源库Oracle 19cLinux 7字符集AL32UTF8目标库Oracle 19cLinux 7字符集AL32UTF8OGG版本19.1.0.0.4企业版DDL复制有几个硬性条件缺一个后面都会出问题源库必须是Oracle 11.2.0.4以上版本19c完全满足。OGG必须是企业版标准版不支持DDL复制只能做DML。这一点要提前确认许可证否则配置到一半才发现版本不支持就尴尬了。源库和目标库字符集最好一致尤其是涉及DDL同步时如果字符集不一致带中文注释或默认值的DDL语句可能乱码。需要为OGG创建独立的数据库用户建议源端目标端使用同名用户便于统一管理。2.2 数据库层准备打开归档与补充日志这一步在源库执行。OGG要读取redo日志来捕获变更所以源库必须处于归档模式。补充日志supplemental log也要打开否则后续如果叠加DML复制会出现日志信息不足的问题。这次虽然只做DDL但生产环境通常后续都会扩展DML复制所以一并开启是正确做法。源库执行SQL shutdown immediate; SQL startup mount; SQL alter database archivelog; SQL alter database add supplemental log data; SQL alter database open; SQL alter system switch logfile;如果源库已经是归档模式不需要上面这段关闭重启的过程但要确认切换窗口最好在业务低峰期操作。Oracle 12c以上还需要开启一个逻辑复制开关这个参数不开启OGG在读取日志时会遇到解析问题SQL alter system set enable_goldengate_replicationtrue scopeboth sid*;目标库不需要开归档和补充日志因为目标端只是应用变更不需要再次被抽取。2.3 创建OGG管理用户与最小权限授予OGG管理用户统一命名为oggadmin。源库和目标库都创建同名用户。建用户和授权的SQL如下SQL create user oggadmin identified by Pssw0rd_ogg; SQL grant connect, resource to oggadmin; SQL grant select any dictionary, select any table to oggadmin; SQL grant alter any table, create any table, create any index to oggadmin; SQL grant drop any table, drop any index to oggadmin; SQL grant execute on dbms_flashback to oggadmin; SQL grant execute on dbms_utility to oggadmin;有两个权限要特别说明。dbms_flashback是OGG启动抽取进程时会调用的包用来保证日志读取的一致性和可见性没有这个权限会报ORA错误。dbms_utility是DDL复制过程中解析对象信息和schema时要用到的。生产环境不建议直接给DBA角色按上面的最小权限给就行。2.4 安装DDL支持对象最容易漏的一步这是OGG DDL复制与纯DML复制最大的区别点。源端必须运行三个SQL脚本它们通常位于OGG安装目录的sql目录下。第一个脚本是ddl_setup.sql需要以SYSDBA身份连接源库执行。这个脚本会创建一组内部对象包括GGS_DDL_HIST、GGS_DDL_OBJ_BEFORE等表以及配套的触发器和包。执行方式SQL connect / as sysdba SQL ddl_setup.sql脚本运行时会要求输入OGG管理用户有些版本可以直接作为参数传入。这里有个坑ddl_setup.sql内部会自动调用同目录下的其他辅助脚本必须确认当前路径正确。另外脚本会检查是否已有旧版本对象如果之前装过其他版本需要先清理。第二个脚本是role_setup.sql用于创建DDL复制角色。执行后脚本会显示一条GRANT语句需要按提示手动执行SQL role_setup.sql SQL grant ggs_ggsuser_role to oggadmin;第三个脚本是ddl_enable.sql用于启用DDL触发器和同步机制SQL ddl_enable.sql这三个脚本是DDL复制能否工作的前提。我第一次配置时漏了role_setup那步结果抽取进程正常运行DDL就是不往目标端走查了半天才发现角色没授权。安装完后可以验证SQL select owner, object_name from dba_objects where owner OGGADMIN and object_name like GGS_DDL%;能看到GGS_DDL_HIST等表说明安装成功。3. 源端核心配置MGR、抽取进程EXTRACT与传输进程DP3.1 创建OGG目录与GLOBALS参数OGG安装好后先建目录结构。切换到OGG安装用户进入ggsci$ ggsci GGSCI create subdirscreate subdirs会一次性创建dirprm、dirrpt、dirdat、dirchk等标准目录不创建这些目录后面add extract时会报错。接着编辑GLOBALS文件这个文件管理全局参数GGSCI edit params ./GLOBALS写入以下内容GGSCHEMA oggadmin CHECKPOINTTABLE oggadmin.checkpointGGSCHEMA指定OGG管理用户因为DDL复制需要调用内部包和视图。CHECKPOINTTABLE指定checkpoint表这个表记录OGG进程读取日志、写入trail的位点保证进程重启后能从断点继续不会重复也不会丢失。生产环境强烈建议配置否则进程重启后会丢失位点可能导致数据重复或丢失。然后添加checkpoint表GGSCI dblogin userid oggadmin, password Pssw0rd_ogg GGSCI add checkpointtable oggadmin.checkpoint目标端同样要执行这一步因为复制进程也要记录checkpoint。3.2 配置并启动管理进程MGRMGR是OGG的总管进程负责启动和停止其他进程、监听远程请求、动态端口分配。编辑MGR参数GGSCI edit params mgr一份最小可行的配置PORT 7809 DYNAMICPORTLIST 7840-7850 AUTOSTART EXTRACT * AUTORESTART EXTRACT *, RETRIES 5, WAITMINUTES 1 USERID oggadmin, PASSWORD Pssw0rd_ogg PURGEOLDEXTRACTS ./dirdat/*, USECHECKPOINTSPORT是MGR监听端口源端和目标端都要设置。DYNAMICPORTLIST是进程间数据传输的动态端口范围如果源和目标之间有防火墙必须把这组端口放通否则会出现MGR能通信但数据一直传不过去的情况。AUTOSTART和AUTORESTART用于自动拉起和重启抽取进程避免进程挂了导致同步中断。PURGEOLDEXTRACTS自动清理已消费完的trail文件不然dirdat目录会慢慢堆满磁盘。配置好后启动GGSCI start mgr GGSCI info mgr正常会显示MANAGER RUNNING。3.3 抽取进程EXTRACTDDL捕获的核心抽取进程是源端最重要的进程负责读取redo和归档日志把DDL和DML变更解析成OGG格式写入本地trail文件。注册抽取进程GGSCI add extract ext1, tranlog, begin now GGSCI add exttrail ./dirdat/lt, extract ext1, megabytes 100tranlog表示数据来源是事务日志。begin now表示从当前时间点开始。如果源库和目标库之前已经做过初始数据同步从当前点开始没问题如果需要从某个历史时间点补数据可以用begin加具体时间戳。add exttrail定义本地trail文件lt是命名前缀megabytes 100表示单个trail文件超过100MB滚动到下一个文件。这个值没有标准答案主要是控制文件数量IO好的环境可以设大一点省得trail文件切来切去。然后编辑抽取进程参数GGSCI edit params ext1核心参数EXTRACT ext1 USERID oggadmin, PASSWORD Pssw0rd_ogg TRANLOGOPTIONS EXCLUDEUSER oggadmin DDL INCLUDE ALL DDLOPTIONS ADDTRANDATA, REPORT WILDCARDRESOLVE DYNAMIC TABLE app_schema.*;TRANLOGOPTIONS EXCLUDEUSER oggadmin很关键告诉抽取进程不要捕获oggadmin自己产生的日志。如果不排除OGG在写checkpoint表、DDL支持表时也会被自己捕获形成无意义的回环和性能损耗。DDL INCLUDE ALL捕获全部DDL。想限制范围可以改成DDL INCLUDE OBJTYPE TABLE只捕获表相关DDL或者用EXCLUDE参数排除某些对象类型。DDLOPTIONS ADDTRANDATA, REPORT中ADDTRANDATA表示当DDL创建新表后自动为新表添加补充日志这样后续对该表做DML时也能被正确捕获REPORT会在OGG报告中记录DDL处理细节排查问题时非常有用。WILDCARDRESOLVE DYNAMIC是动态解析通配符。配合TABLE app_schema.*使用新创建的表也能被自动捕获。不加这个参数配置时不存在的表不会被抽取。启动抽取进程GGSCI start ext1 GGSCI info ext1状态应该是RUNNINGLag为0。如果状态是STOPPED用view report ext1查看报告定位原因。3.4 传输进程PUMP把trail送到目标端抽取进程抓到变更写入本地trail后还需要传输进程Data Pump把trail通过网络发送到目标端。为什么不让EXTRACT直接远程传输因为本地trail相当于一个缓冲层。如果网络瞬断数据已经安全落在本地trail里恢复后Pump重新连接继续传不会丢数据。源库压力大的场景下这个设计能有效解耦抽取和传输。注册传输进程GGSCI add extract dp1, exttrailsource ./dirdat/lt GGSCI add rmttrail ./dirdat/rt, extract dp1, megabytes 100exttrailsource指定DP读取的本地trail文件rmttrail定义目标端接收落地时的trail文件名。配置参数GGSCI edit params dp1EXTRACT dp1 PASSTHRU USERID oggadmin, PASSWORD Pssw0rd_ogg RMTHOST 10.10.10.20, MGRPORT 7809 RMTTRAIL ./dirdat/rt TABLE app_schema.*;PASSTHRU表示传输进程不需要解析和转换数据只做透传性能开销很小。RMTHOST是目标主机IPMGRPORT是对端MGR监听端口。TABLE范围必须和EXTRACT保持一致否则传输不完整。启动DP进程源端配置到这里就完成了。4. 目标端复制配置REPLICAT与DDL应用策略源端负责抓取和传输目标端靠REPLICAT进程接收trail并在目标库重放。目标端配置相对简单但对DDL参数的处理一样不能马虎。4.1 目标端基础初始化目标端需要完成后台准备安装OGG并执行create subdirs创建oggadmin用户并授权权限和源端一致配置GLOBALS文件GGSCHEMA oggadmin CHECKPOINTTABLE oggadmin.checkpoint添加checkpoint表GGSCI dblogin userid oggadmin, password Pssw0rd_ogg GGSCI add checkpointtable oggadmin.checkpoint配置并启动MGR参数与源端一致。目标端不需要运行DDL支持脚本因为它只是应用方。如果误在目标端也装了DDL支持对象反而可能干扰REPLICAT进程对DDL的判断。4.2 注册REPLICAT进程目标端接收trail文件路径是dirdat/rt注册复制进程GGSCI add replicat rep1, exttrail ./dirdat/rt, checkpointtable oggadmin.checkpointcheckpointtable的作用和源端一样记录REPLICAT的应用位点。不加checkpointtable进程重启后可能重复应用部分操作这在DDL复制场景下会造成目标库对象重复创建或报错。4.3 复制进程参数配置编辑REPLICAT参数GGSCI edit params rep1REPLICAT rep1 USERID oggadmin, PASSWORD Pssw0rd_ogg DDL INCLUDE ALL DDLOPTIONS NOCROSSUSER, REPORT ASSUMETARGETDEFS DISCARDFILE ./dirrpt/rep1.dsc, APPEND, MEGABYTES 100 MAP app_schema.*, TARGET app_schema.*;DDL INCLUDE ALL允许复制进程应用所有DDL。DDLOPTIONS NOCROSSUSER, REPORT中的NOCROSSUSER值得单独讲。它表示如果源端执行的DDL是某个用户发起的但对象所属schema是另一个用户那么这条DDL不会被复制。比如运维人员偶尔用SYS账号做了某些操作但这些操作涉及SYS对象NOCROSSUSER会挡掉避免系统内部对象被同步到目标端。对本次需求很合适业务结构变更都是app_schema用户发出的而SYS的杂项操作不应该被复制。ASSUMETARGETDEFS表示源端和目标端表结构完全一致REPLICAT不需要查询源端定义文件直接按目标端现有结构应用。本次是同构库且DDL会同步结构所以选它。如果目标端表结构存在差异需要用SOURCEDEFS配合定义文件。DISCARDFILE是应用失败时记录错误语句的文件排错最重要的线索之一APPEND表示追加而不是覆盖。另外DDLOPTIONS的子参数远不止NOCROSSUSER和REPORT其他像ALLOWEMPTY、ADDNUMERICSTRINGS、GLOBALTRACE等普通场景用不上。不建议一上来就把一整套参数堆进去参数越多越难排查。核心参数配好跑通后再按需增加。配置完成后启动GGSCI start rep1 GGSCI info rep1此刻三端进程全部RUNNING配置阶段结束。5. 实操验证观察DDL复制是否真的生效配置完成不代表万事大吉必须实测一轮完整DDL从建表、加字段到TRUNCATE、DROP都要验证。我当时按下面这个顺序逐步确认。5.1 验证建表在源库执行SQL create table app_schema.t_ddl_test ( id number primary key, name varchar2(50), create_time date default sysdate );然后立刻去目标库执行SQL describe app_schema.t_ddl_test;正常情况下目标库已经存在这张表结构完全一致。如果没出现先看REPLICAT进程有没有报错GGSCI view report rep1再查discard文件$ tail -100 $OGG_HOME/dirrpt/rep1.dsc5.2 验证ALTER TABLE源库加列SQL alter table app_schema.t_ddl_test add (remark varchar2(200));目标库马上查表结构应该多出REMARK列。再测试改字段长度SQL alter table app_schema.t_ddl_test modify (name varchar2(100));目标库的NAME字段长度也应该同步变化。5.3 验证TRUNCATETRUNCATE在Oracle里属于DDL不在DML范围内但它常见且容易漏。源库插入数据后执行SQL insert into t_ddl_test values (1, test, sysdate); SQL commit; SQL truncate table app_schema.t_ddl_test;目标端对应表应该也被清空。5.4 验证DROP和重建最后测删除SQL drop table app_schema.t_ddl_test purge;目标端确认表已不存在。还可以反向测试源库创建一个不在复制范围内的表比如其他用户下的表确认目标端不出现验证范围过滤生效。5.5 查看OGG后台跟踪验证过程不能只看数据库结果还要通过OGG自己的命令观察数据流。GGSCI stats ext1 GGSCI stats dp1 GGSCI stats rep1分别查看抽取、传输、复制进程处理了多少操作。还有一个非常实用的视图SQL select * from ggs_ddl_hist order by 1 desc;这里记录了OGG捕获并处理过的每条DDL的历史。如果这里都没有记录说明源端捕获就有问题都不用等目标端反馈。每次验证后建议把lag命令作为固定动作GGSCI lag ext1, dp1, rep1lag长期非0说明某个环节处理不过来需要排查。6. 常见问题与排查技巧实录这一部分是最值得反复看的。下面这些问题都是配置过程中遇到过的按踩坑频率排序。6.1 DDL复制完全没反应症状源端建表目标端没反应EXTRACT和REPLICAT进程都是RUNNING数据库也没有报错。排查顺序确认源端是否安装了DDL支持对象。用oggadmin查询GGS_DDL_HIST表如果报错表不存在说明ddl_setup.sql没执行成功。确认EXTRACT参数中是否写了DDL INCLUDE ALL。漏掉DDL行相当于只同步DML不同步DDL。确认REPLICAT参数中是否写了DDL INCLUDE ALL这一步同样容易漏。确认OGG版本是否为企业版标准版不支持DDL复制。6.2 提示没有GGS角色权限配置阶段常遇到权限错误比如ORA-01031 insufficient privileges。原因多半是角色没授权。需要重新执行SQL role_setup.sql SQL grant ggs_ggsuser_role to oggadmin; SQL ddl_enable.sql顺序不能乱先角色后启用。6.3 TRUNCATE没有被复制Oracle里TRUNCATE是DDL但日志记录方式和普通DML不同。如果DDL参数配置正确TRUNCATE应该能复制。有一种情况容易漏源库使用了TRUNCATE PARTITION或ALTER TABLE TRUNCATE PARTITION这类语句OGG有时识别成ALTER TABLE。不用太担心只要DDL复制整体正常一般不会丢但可以在GGS_DDL_HIST里查看实际记录类型做到心里有数。6.4 新表没有补充日志导致DML报错症状DDL复制正常建表能同步。但新表创建后源库对该表做DML时目标端报missing supplemental log data。原因EXTRACT参数没有DDLOPTIONS ADDTRANDATA新建表后没有自动添加补充日志。解决办法在EXTRACT参数中加入DDLOPTIONS ADDTRANDATA该参数只对之后新建的表生效。对已有表手动补充SQL alter table app_schema.t_ddl_test add supplemental log data (primary key) columns;强烈建议第一时间把ADDTRANDATA加上否则每次DDL建的新表都手工补日志早晚会漏。6.5 checkpoint表冲突或不存在错误类似ERROR OGG-00446 Checkpoint table oggadmin.checkpoint does not exist。原因要么是没执行add checkpointtable要么是GLOBALS里写的表名和实际不一致。这里注意checkpoint表必须手动addOGG不会自动创建而且MGR、EXTRACT、REPLICAT都需要正确权限去读写它。6.6 字符集转换问题同构库且字符集一致时通常没事。但如果目标库是ZHS16GBK、源库是AL32UTF8DDL语句里的中文注释或默认值可能乱码。处理方式源库和目标库字符集尽量统一确实不一致时考虑在参数中配置SOURCECHARSET或TARGETCHARSET但DDL复制的字符集转换能力有限最稳妥还是统一字符集。6.7 端口不通导致传输滞留现象EXTRACT正常运行但DP的Lag持续增长目标端完全没有数据。排查先ping目标IP再用telnet测试MGR端口7809通不通。OGG进程间数据传输走的是DYNAMICPORTLIST里的动态端口只放行7809远远不够。有一次客户环境只开了7809端口结果MGR通信正常但trail文件迟迟不到目标端把7840-7850放通后数据马上传过去了。6.8 SYS账号操作引发DDL误同步如果目标库出现预期外的对象比如SYS创建的临时结构也被同步过来多半是没配DDLOPTIONS NOCROSSUSER或者捕获范围写得太宽。在REPLICAT参数中加回NOCROSSUSER把源端TABLE范围收窄这类误同步基本能解决。7. 写在最后这是一次让我印象深刻的配置实践这次配置OGG DDL单项复制前后花了接近两天一半时间在等权限审批和网络策略确认一半时间真正敲命令和排错。真正配好并且看到目标端新表自动出现的那一刻最大的感受是这工具确实能力够强但要求你前期把每一层都弄明白再动手。我个人的体会DDL复制比DML复制娇贵不少。DML复制只要日志权限对、表映射对基本就通了。DDL复制牵扯到源端DDL支持对象、角色授权、GLOBALS配置、EXTRACT和REPLICAT的DDL参数组合任何一层出问题都表现为进程看着没问题但表就是不过来。所以如果你也在配置OGG DDL单项复制一定把DDL支持脚本安装、NOCROSSUSER、ADDTRANDATA这几个关键点记牢。另外强烈建议配置完成后做一轮完整的DDL验证从CREATE到ALTER再到DROP和TRUNCATE全部过一遍别只测一个建表就宣布成功。把整个验证过程和命令输出记录下来后面出问题可以通过对比正常输出来判断是哪里发生了变化。我后续也在考虑把这套环境扩展到DDL加DML全量单向同步。两者配置有很多共通之处但DML部分涉及初始数据同步和冲突处理又是一套新玩法。这次先分享到这里希望这篇配置记录对正在折腾OGG的朋友有实际帮助。