news 2026/10/21 7:40:37

CentOS 7下Oracle 11g CDC与GoldenGate配置实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CentOS 7下Oracle 11g CDC与GoldenGate配置实战

上个月帮一个内部数据团队处理“CentOS 7 下 Oracle 11g CDC 配置”这件事,折腾了两三个周末,最后把整套从环境准备到增量实时同步的链路跑通了。CentOS 7 配 Oracle 11g 本来就不在官方推荐组合里,再加 CDC 需求,中间的坑不算少。这篇总结把配置过程和排错经验都整理出来,给同样在这套组合上做数据同步的同学做个参照。

先说 CDC 解决什么问题。业务系统里的订单表、库存表每天都在大量更新,数据仓库、实时大屏、下游分析库都想知道这些变更。如果靠定时全量抽取,数据延迟高、效率低;如果靠应用层埋点改代码,侵入性太强。变更数据捕获(Change Data Capture,CDC)能直接读数据库日志,把 insert、update、delete 操作原样抓出来,再投递给目标端。整个过程中源库几乎无感知,这才是生产环境最想要的效果。

本文章也增加对应实战场景讲解。

1. 方案为什么这样定?

1.1 业务场景与核心需求分析

拿这次的具体案例来说,业务方提供了一套比较典型的“订单+库存”场景,核心表大概在五十张左右,日增数据量不是特别夸张,但更新频率很高,每晚会有批处理大批量变更。客户端要求:数据延迟不能超过一分钟,目标端是另一套数据库,供报表和数据分析用。

在这个前提下,第一反应就是排除“双写”“应用层发消息”这类侵入式方案,因为改业务代码的代价太高,牵扯的团队太多。CDC 方案就成了必然选择。至于用哪种 CDC 技术,下面仔细对比一下。

1.2 Oracle 原生 CDC 的三条实现路线

Oracle 11g 时代,想做 CDC 基本是这三条路线:

路线实现方式对源库影响部署成本适用场景
GoldenGate(OGG)读取在线日志与归档日志,专职进程捕获极低,只读日志较高,需要单独部署大规模、生产级别的实时同步,主流选择
LogMiner 自己挖用 LogMiner 接口解析日志还原 SQL有解析开销,对归档日志有依赖低,无需额外安装软件小规模表、临时性分析、内部工具
时间戳+触发器表上建触发器,记录变更时间戳和旧值对业务表侵入明显,性能开销大最低几乎只适合功能演示或低压场景

从运维角度看,触发器方案只要上线,性能风险基本不可控;LogMiner 方案解析日志本身也有性能损耗,而且对归档日志的保留策略要求很严。OGG 是专门的日志同步工具,架构上把捕获和应用两个角色拆开,源端压力小、目标端可控,是决定用它的根本原因。

1.3 补充日志与归档模式为什么是 CDC 的“地基”

OGG 是基于日志的同步,前提就是数据库把日志写完整。有两个开关必须在配置前确认好:

第一,归档模式必须开启。OGG 的抽取进程有时需要读取旧日志,如果你关了归档,日志被覆盖之后数据就断了,OGG 只能从头再来或者报错。开启方式是:

-- 查看当前信息 archive log list; -- 如果非归档模式,需要调整后重启数据库 shutdown immediate; startup mount; alter database archivelog; alter database open;

执行完建议立即做一次全量备份。

第二,补充日志必须开启。默认日志里不会记录“更新前的整行镜像”,没有补充日志,OGG 拿到 update 语句时可能缺少足够的列来执行 where 条件。最保险的做法是开启数据库级补充日志:

alter database add supplemental log data;

也可以只对单表开启列级补充日志,但在生产环境中,表多且经常变动时,数据库级补充日志更省心。

2. CentOS 7 上把 Oracle 11g 先跑稳

2.1 系统依赖与内核参数

Oracle 11g 在 CentOS 7 上不属于官方正式支持组合,但这并不代表跑不起来。实际验证下来,把几个关键依赖补齐后,稳定性完全够用。需要先安装这些软件包:

yum install -y binutils compat-libcap1 compat-libstdc++-33 \ gcc gcc-c++ glibc glibc-devel ksh libaio libaio-devel \ libgcc libstdc++ libstdc++-devel libXext libXtst libX11 \ libXau libXi make sysstat unixODBC unixODBC-devel

注意 compat-libstdc++-33 在 CentOS 7 的默认源里可能没有,需要先确认源配置。如果没有这个包,Oracle 的安装向导会报缺少依赖,有时候跳过也能装上,但后续运行 OGG 时可能遇到莫名其妙的问题,还是补齐为妙。

内核参数在/etc/sysctl.conf里加:

fs.aio-max-nr = 1048576 fs.file-max = 6815744 kernel.sem = 250 32000 100 128 kernel.shmall = 1073741824 kernel.shmmax = 34359738368 net.core.rmem_default = 262144 net.core.rmem_max = 4194304 net.core.wmem_default = 262144 net.core.wmem_max = 4194304 net.ipv4.ip_local_port_range = 9000 65500

然后sysctl -p生效。这些参数是 Oracle 官方针对 Linux x86-64 的推荐值,不需要太纠结,直接拿来用即可。

2.2 关键系统配置:关闭 THP

透明大页(Transparent Huge Pages,THP)是 CentOS 7 默认开启的特性,但它和 Oracle 数据库的交互并不好,经常导致内存分配不稳定、性能抖动。Oracle 官方也明确建议关闭 THP。关闭方式:

echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag

但这两个命令重启后会失效,所以要加入/etc/rc.d/rc.local并在 CentOS 7 里赋予执行权限:

chmod +x /etc/rc.d/rc.local

有人会问,SELinux 要不要关?实践来看,为了省事,测试环境可以直接setenforce 0,生产环境建议至少设为 permissive,或者把对应的 Oracle 目录都加上 SELinux 上下文,不然监听和数据库进程容易莫名其妙起不来。这次在生产环境直接采用了 permissive 模式,到目前为止没有新的问题。

2.3 数据库用户与网络端口准备

CDC 需要一个专门的数据库账号来连接源库。出于安全考虑,别直接用 system 或 sys 账号干活。创建账号并授权时,OGG 需要的权限有一定要求,下面是常用的一套组合:

create user ogg_user identified by "StrongPass123" default tablespace users temporary tablespace temp; grant connect, resource to ogg_user; grant select any dictionary to ogg_user; grant select any transaction to ogg_user; grant flashback to ogg_user; grant create session to ogg_user;

网络方面,数据库监听 1521 端口要保证可用,OGG 的 Manager 端口(例如 7809)也要在防火墙里开放。CentOS 7 里如果开着 firewalld,可以使用:

firewall-cmd --permanent --add-port=1521/tcp firewall-cmd --permanent --add-port=7809/tcp firewall-cmd --reload

2.4 归档目录与磁盘空间的前瞻规划

开启归档之后,最容易犯的错是归档目录空间规划不足。假设业务每天产生 10GB 归档日志,而你只留了 20GB 空间,即便 OGG 在消费也已经很危险。建议归档目录独立挂载,并至少按“日常日志量 × 3 天”的动态空间 + 缓冲估算。另外把归档日志的自动清理做好:

-- 查看闪回恢复区和归档目标的空间使用 select * from v$recovery_file_dest;

如果用的是db_recovery_file_dest,别忘记设置合理的db_recovery_file_dest_size。OGG 消费归档日志的速度有时候受大事务影响变慢,这时归档空间告急会连锁导致数据库 hang,这是个必须预先控制住的点。

3. GoldenGate 配置实录:从安装到增量同步跑通

3.1 OGG 安装布局与环境变量

OGG 软件包安装很直接,把对应的 Linux x64 版本解压到指定目录即可。建议放在/opt/ogg,不要放在 Oracle 数据库软件的目录里,保持职责分离。安装完成后第一件事是创建子目录:

cd /opt/ogg ./ggsci GGSCI> create subdirs

这一步会生成 dirprm、dirrpt、dirtmp、dirchk 等目录结构,后续所有配置都围绕这些目录展开。

OGG 运行需要的环境变量,主要是找到 Oracle 的客户端库。在/etc/profile或者oracle用户的环境变量里设置:

export ORACLE_BASE=/u01/app/oracle export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/dbhome_1 export OGG_HOME=/opt/ogg export PATH=$PATH:$ORACLE_HOME/bin:$OGG_HOME export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$OGG_HOME:$LD_LIBRARY_PATH

关于LD_LIBRARY_PATH排在前面还是后面,遇到过这样的坑:如果环境变量里的库搜索顺序不对,OGG 启动时可能加载到系统自带的 libclntsh 版本,导致 OGG 连接数据库直接报 OCI 错误。这里可以直接把$ORACLE_HOME/lib放在最前面,实测最稳。

3.2 Manager 进程:所有进程的总管家

OGG 的 Manager 负责启动、监控、重启其他进程,是所有进程的守护者。配置 Manager 用 GGSCI 命令行:

GGSCI> edit params mgr

文件内容写:

PORT 7809 DYNAMICPORTLIST 7810-7830 AUTORESTART EXTRACT *, RETRIES 5, WAITMINUTES 3 PURGEOLDEXTRACTS ./dirdat/*, USECHECKPOINTS, MINKEEPHOURS 12
  • PORT是 OGG 主监听端口,要跟防火墙开的端口对上。
  • DYNAMICPORTLIST是数据投递时使用的动态端口范围。
  • AUTORESTART让 Manager 在抽取进程意外退出时自动拉起,这里 5 次重试、间隔 3 分钟。
  • PURGEOLDEXTRACTS用来自动清理本地 trail 文件,避免磁盘被塞满。

配置完成后启动:

GGSCI> start mgr GGSCI> info mgr

看到 status 为 RUNNING,Manager 就位了。

3.3 源端 Extract 抽取进程配置

抽取进程是 OGG 最核心的部分,它直接读取数据库的在线日志和归档日志。开始之前先连接到数据库:

GGSCI> dblogin userid ogg_user@源库服务名, password StrongPass123

如果要支持 OGG 对表的补全日志,还需要在源库上执行:

GGSCI> add trandata schema_name.table_name

这个命令的作用等同于数据库层面的补充日志增强,它会生成触发器和日志规则,让 OGG 能拿到完整的旧值信息。如果你希望属性定制,也可以手动用 SQL 的方式执行:

alter table schema_name.table_name add supplemental log data (all) columns;

再创建抽取进程。参数文件命名要和进程名对应,例如进程名 EXT_ORD,参数文件就是dirprm/EXT_ORD.prm:

GGSCI> edit params EXT_ORD

内容大致如下:

EXTRACT EXT_ORD USERID ogg_user@源库服务名, PASSWORD StrongPass123 EXTTRAIL ./dirdat/lt TABLE schema_name.orders; TABLE schema_name.inventory; TABLE schema_name.order_items;

关键点是EXTTRAIL指定了本地 trail 文件目录,后续投递进程数据从从这里读。

创建日志记录点:

GGSCI> add extract EXT_ORD, tranlog, begin now GGSCI> add exttrail ./dirdat/lt, extract EXT_ORD

tranlog表示这是在线日志抽取方式,begin now表示从当前时刻开始捕获。如果业务需要把存量数据也同步过去,这里要配合后面说的初始化方案。

启动 Extract:

GGSCI> start EXT_ORD GGSCI> info EXT_ORD

看 report 显示无 error,而且每秒有事务记录继续追加,说明抽取进程在正常工作。

3.4 Data Pump 投递进程配置

在源端,除了 Extract 进程,通常会再配置一个 Data Pump 进程,负责把本地 trail 传到目标端。这么做的好处是:本地 trail 可以先快速写入,即使目标端网络抖动,Extract 也不会被阻塞。配置如下:

GGSCI> edit params DPMP_ORD

内容:

EXTRACT DPMP_ORD PASSTHRU RMTHOST 目标端IP, MGRPORT 7809 RMTTRAIL ./dirdat/lt TABLE schema_name.orders; TABLE schema_name.inventory; TABLE schema_name.order_items;

然后添加进程映射:

GGSCI> add extract DPMP_ORD, exttrailsource ./dirdat/lt GGSCI> add rmttrail ./dirdat/lt, extract DPMP_ORD

注意这里的exttrailsource指向的是上一节 Extract 进程写入的本地 trail,投递进程会从那里读并转发到目标端。

3.5 目标端 Replicat 应用进程配置

在目标端数据库(同为 Oracle 11g)上,首先要建立对应的 schema 和表结构。如果业务表结构一致,直接用CREATE TABLE AS SELECT初始化就可以;不一致就要靠 OGG 的映射规则来处理。

目标端 OGG 进程叫 Replicat,参数文件如REP_ORD.prm:

REPLICAT REP_ORD USERID ogg_user@目标库服务名, PASSWORD StrongPass123 MAP schema_name.orders, TARGET schema_name.orders; MAP schema_name.inventory, TARGET schema_name.inventory; MAP schema_name.order_items, TARGET schema_name.order_items;

这里MAP是源表与目标表的映射关系。如果目标表名、字段名和源表不完全一致,可以加列映射:

MAP schema_name.orders, TARGET report_schema.orders, COLMAP (order_id = order_id, order_status = order_status, create_time = create_time);

然后添加 Replicat 进程:

GGSCI> add replicat REP_ORD, exttrail ./dirdat/lt GGSCI> start REP_ORD

Replicat 启动后,会读取目标端本地 trail(由源端 Data Pump 传过来)并应用到目标库。

3.6 存量数据初始化方案

增量同步启动后,存量数据还得并进来,这就需要一个初始化方案。OGG 提供几种方式,最常用的是:先在目标端用 expdp/impdp 或 SQL 方式批量导入存量数据,再启动 Extract。关键在于保证“存量导入”和“增量捕获”两个动作的衔接点一致。

操作思路是:

  1. 先启动 Extract(但不启动 Replicat)。
  2. 数据库层面用一致性快照导出存量数据(expdp 参数flashback_time或者闪回查询)。
  3. 把存量数据导入目标端。
  4. 启动 Replicat,让增量数据从 checkpoint 位置继续应用。

这里有个容易搞错的口诀:先启动抽取,后启动应用;数据导出的时间点要和抽取进程的 checkpoint 时间一致,否则会出现存量数据与增量数据重叠或丢失。实际生产环境里,通常会选择业务低峰期做初始化,减少出错的概率。

另外,OGG 有个ADD EXTRACT ... BEGIN NOW的含义要搞清楚,它不是指“从现在才收集所有增量”,而是从发出这个命令的记录点开始收集。所以只要初始化数据是同一时刻的快照,衔接时不会丢。

4. 没装 GoldenGate 也能做:LogMiner 轻量方案

4.1 LogMiner 原理和适用边界

如果只是临时需要抓取几张表的变更记录,或者不想引入整套 OGG 组件,Oracle 自带的 LogMiner 也能实现类似效果。LogMiner 的原理是读重做日志和归档日志,通过DBMS_LOGMNR包解析成 SQL 语句,然后从内存视图里查询。

它的局限也很明显:日志解析是在数据库里做的,SQL 级别重建效率低,大事务、大批量任务会把性能拖垮。另外它处理的是“已经提交”的事务,实时性不如 OGG,数据量大了之后维护成本高。所以我的建议是:数据量小、业务容忍秒级甚至分钟级延迟,用它做临时方案没问题;真要长期跑,还是得 OGG。

4.2 快速启用手把手步骤

LogMiner 的配置过程分成三步。

第一步,补充日志还是要开(和 OGG 的道理相同):

alter database add supplemental log data;

第二步,构建字典文件。字典的作用是把日志里的内部对象 ID 翻译成可读的表名列名:

begin dbms_logmnr_d.build( dictionary_filename => 'dict.ora', dictionary_location => '/oracle/logmnr' ); end;

注意给 Oracle 进程足够的权限来写这个目录。

第三步,选择需要解析的日志文件列表,然后启动 LogMiner:

begin dbms_logmnr.add_logfile( logfilename => '/oracle/oradata/orcl/archivelog/1_1234_1234567890.arc', options => dbms_logmnr.new ); dbms_logmnr.start_logmnr( dictfilename => '/oracle/logmnr/dict.ora', options => dbms_logmnr.dict_from_online_catalog ); end;

最后查询变更记录:

select scn, timestamp, seg_owner, seg_name, operation, undo_sql, redo_sql from v$logmnr_contents where seg_name = 'ORDERS' and timestamp between to_date('2024-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss') and to_date('2024-01-02 00:00:00','yyyy-mm-dd hh24:mi:ss') order by scn;

从v$logmnr_contents里能看到 redo_sql(重做后的语句片段)和 undo_sql(回滚 SQL)。需要把这两列组合起来还原完整操作。

LogMiner 的实战局限是:解析日志时,如果归档日志很多,v$logmnr_contents的结果集可能巨大,查询时很容易内存溢出,建议加SEG_NAME、时间范围等条件缩小范围。另外它不会自动跟踪 DML 的键值,无法直接当持续同步管道用。这个方案其实是备胎,适合“拉取过去几天某张表的变更”这种即席需求。

5. 生产实战中踩过的坑与排查速查

5.1 OGG 进程老挂/起不来

OGG 进程起不来,最典型的几个现象和原因:

  • ERROR OGG-00228,管理员说 “Duplicate extract or primary extract name”。原因是进程名重复或者旧进程没清理干净。确认进程列表后delete extract重建即可。
  • 启动时报告 OCI 错误,大部分是LD_LIBRARY_PATH没弄好,导致 OGG 加载 Oracle 客户端库失败。把$ORACLE_HOME/lib放最前面,重新开 shell 再试。
  • 提示表不存在或没有权限,先确认dblogin userid连上了哪个用户,并该用户有select any table权限。

5.2 归档日志暴涨,OGG 消费不过来

这个坑在开启 CDC 后才暴露出来。归档日志的生成速度突然变快,往往是 OGG 的抽取进程在某张大表上落了一个超长事务,日志量瞬间放大。排查思路:

  1. 看info extract,如果 Redo Logs 列表积压很多文件,说明消费不畅。
  2. 看 OGG 进程 report,是否有LOGREADERtimeout 等待。
  3. 针对大表做优化:分表、控制单事务大小,或者在 OGG 参数里开启并发抽取。

还有一个很容易漏的点:数据库supplemental log data (all) columns如果设置成 ALL,每次更新都会把整行所有列写入日志,日志量可能翻好几倍。只要能满足同步需求,尽量只对必要表用列级补充日志,而不是全局 ALL。

5.3 时间与字符集不一致导致脏数据

CDC 同步过程中,时区不一致的坑非常隐蔽。源库和目标库的系统时区不同,OGG 抽取日志里的时间戳是带时区的,目标端如果不做转换,就会看到数据晚了一小时或者早了一小时。解决方法是源端和目标端统一SYSTEMTIMEZONE,或者在 OGG 映射里显式转换:

MAP schema_name.orders, TARGET schema_name.orders, COLMAP (create_time = @GETENV('DBTIMEZONE'))

字符集不一致的坑也见过很多,源库是 ZHS16GBK,目标库是 AL32UTF8,中文出现乱码。OGG 本身不转换字符集,需要提前确认两端数据库字符集能互通,并通过NLS_LANG设置好环境变量。建议在源端:

export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

目标端根据目标库字符集设置,例如:

export NLS_LANG=AMERICAN_AMERICA.AL32UTF8

5.4 大表初始化失败的处置

初始化五十张大表期间,遇到过 impdp 到一半中断,重新导入时又要重头再来。后来采取的方案是把大表按分区拆成多个任务,每张表单独导出导入,导入完成后先增量对账,再继续后续表。这样即使某个分区失败,影响范围也被隔离了。

初始化衔接时还遇到过数据重复:存量导入完成前,增量进程已经启动,导致目标端既有导入的旧数据,又应用了增量 update/delete,出现主键冲突。这次教训让我明确了流程顺序——先知性启动抽取进程收取增量,再倒存量,再启动复制进程。顺序不能搞反。

5.5 错误信息速查表

错误现象可能原因处理动作
OGG-00228抽取进程名重复查看并清理旧进程,重建
OGG-01003源表和目标表结构不匹配核对列定义,用 COLMAP 调整映射
OGG-00423目标表不存在或权限不足检查目标端表结构和 OGG 用户权限
ORA-01031权限不足按前面授权清单补 grant
OGG-01224trail 文件目录空间不足清理 trail 或扩展磁盘
OGG-00731找不到检查点文件从dirchk目录恢复或重建 checkpoint
ORA-00600 内部错误(归档解析)多为版本兼容问题确认 OGG 与数据库版本匹配,升级 OGG 补丁

6. 个人实操体会

这套组合从选型到上线,我最大的体会是:CDC 项目往往不是难在配置本身,而是难在环境提前量的控制。CentOS 7 + Oracle 11g 本身就是老系统组合,装数据库时如果能一次性把依赖、内核参数、THP、SELinux 都打点好,后面 CDC 的稳定性会省很多事。如果只想着“先把数据库装上再说”,等 OGG 跑起来再回头补环境参数,排查成本会翻倍。

另外,凡是做日志级 CDC,一定要把“归档日志空间”当一等公民看待。很多问题表象是 OGG 进程挂掉,深挖之后发现根因是归档日志把磁盘写满,数据库直接 hang 了。提前想好档案保留策略、监控归档增长趋势,比天天盯进程状态有效得多。

配置完成之后,建议写一个简单的监控脚本,定时检查 OGGinfo all的状态,以及源端归档日志的生成速度。脚本逻辑很简单:把info all里的进程状态和大表归档增量数抓出来,超过阈值就发告警。这一点虽然不是必须,但在生产环境里绝对能救急。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 7:40:13

小聆AI复刻MOSS:语音助手自定义角色全流程实战指南

做语音助手自定义角色这件事,我从去年开始就一直在折腾。前阵子朋友随口问了一句:“能不能在‘小聆AI’里把电影里那个MOSS复刻出来?”我当时觉得这事儿既有挑战又好玩,就上手了。整个项目前后花了大约两周时间,真正做…

作者头像 李华
网站建设 2026/10/21 7:38:24

PyTorch DataLoader加载高光谱数据实战指南

简介:这套资料面向正在使用PyTorch处理高光谱影像的深度学习开发者,系统讲解如何通过DataLoader高效完成数据读取、预处理、批处理与多线程加载。内容覆盖Dataset子类编写、光谱归一化、batch_size与num_workers调优、shuffle增强、pin_memory加速及自定…

作者头像 李华
网站建设 2026/10/21 7:37:02

STM32F4无感FOC高频注入:零低速启动的软硬件工程实践

做无感FOC的应该都有过这种经历:中高速段用反电动势观测器跑得好好的,转速一掉到几百转以下,估算角度就开始抖,电流波形跟着开叉,严重一点直接触发过流保护。这不是环路参数没调好,而是反电动势观测器在零低…

作者头像 李华
网站建设 2026/10/21 7:35:59

从零搭建一个能干活儿的Bot:环境配置、建Bot与拉群实战

1. 从零搭建一个能干活儿的 Bot:整体思路与方案选型很多人第一次接触 Bot 搭建,脑子里冒出来的第一个念头是“这玩意儿是不是得先学一堆编程语言、再搞个服务器、还得配数据库”。我一开始也这么想,后来实际走了一遍才发现,如果只…

作者头像 李华
网站建设 2026/10/21 7:35:08

Pwn入门必看:汇编基础与Linux内存模型全拆解

CTF Pwn模块系列分享(二):汇编基础Linux内存模型拆解上一篇文章写了Pwn环境搭建和工具链配置,当时就有朋友在评论区说:环境是搭好了,pwndbg也装上了,但打开第一道入门题,反汇编窗口一…

作者头像 李华
网站建设 2026/10/21 7:34:46

CMSIS-DAP协议核心命令数据包逐字节拆解与调试实战

平时我自己做调试器固件和工具链适配的时候,最常干的一件事就是对着CMSIS-DAP协议的数据包发呆。命令手册翻过很多遍,但真正到了要自己组包、抓包、定位“为什么上位机连不上”的时候,需要的不是“知道有个命令叫DAP_Transfer”,而…

作者头像 李华