ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Windows到Linux的Oracle OGG跨平台增量数据同步实践

Windows到Linux的Oracle OGG跨平台增量数据同步实践

简介:面向Oracle DBA与数据同步实施人员的一份OGG部署实操文档,聚焦Windows源库向Linux目标库进行Oracle GoldenGate 12.2.0.2数据同步的完整落地过程。压缩包仅含1个PDF文件,约496KB,篇幅精炼,适合按章节查阅与实验对照。内容覆盖源库归档、强制日志与附加日志开启,goldengate用户及权限配置,目标库授权差异,OGG解压与可视化安装、子目录初始化、GLOBALS与checkpoint表设置,以及Manager、Extractor、Replicat组件配置要点;同时给出监控、日志管理与故障排查思路,便于读者搭建跨平台同步链路并定位常见配置问题。已有298人学习,可作为异构环境数据复制入门与部署排错的参考材料。

1. 从 Windows 到 Linux 的数据同步,OGG 这套链路到底怎么搭

生产库跑在一台 Windows 机器的 Oracle 实例上,报表侧要整体搬到 Linux 的新机器,中间只给了 4 小时停机窗口——这种局面下指望全量导入再追一次增量,基本等于赌运气。我头一回接 oracle linux OGG 数据同步这类需求时,也怀疑过跨操作系统能不能直接复制;实际搭完才确认,OGG 的抽取端只读源库 redo 与归档日志,复制端只认 trail 文件和 SQL,操作系统差异被 trail 这层抽象吃掉了,Windows 到 Linux 是它的常规用法,不是偏门场景。

这套链路的现实价值很直接:不停机把增量持续送到目标端,中途出错还能按 SCN 回退重放,而不是推倒重来。它适合手上已经有 OGG 安装介质、要自己完整落地一次的 DBA 和后端工程师,也适合已经在跑 OGG、却被跨平台参数和端口规划绊过的人。下面按“库要调成什么样 → 软件怎么装 → 进程怎么配 → 初始化怎么对齐 → 哪儿最容易翻车”的顺序拆。

2. 数据库侧先调成“能抽日志”的状态:四个开关与一套账号权限

OGG 抽取不是定时查表,它读的是源库的在线 redo 和归档日志。所以数据库这一层没配置到位,后面进程参数写得再漂亮也跑不起来。这一章把源库、目标库分别要做什么讲清楚,重点是几个容易只做一半的地方:归档开了但强制日志没开、附加日志加了但没切日志生效、12c 的参数在 11g 上根本不存在。

2.1 源库四个开关:归档、force logging、附加日志、enable_goldengate_replication

Windows 源库这一侧,先用 sysdba 登录确认现状,再决定改哪几个。归档模式是地基,没开归档就没有可读的历史日志;强制日志是为了堵住 nologging 操作的漏洞——直接路径插入、索引 rebuild 这类操作在 nologging 下不写 redo,OGG 抽不到对应行,目标端就会出现“数据少了一截但进程一切正常”的玄学现象;数据库级附加日志是给后续表级 trandata 打底。

-- 1) 先看现状,已经在归档模式就跳过切换步骤 archive log list; -- 2) 未归档时开启,需要重启到 mount 状态 shutdown immediate; startup mount; alter database archivelog; alter database open; -- 3) 强制记录日志,防止 nologging 操作绕过 redo alter database force logging; -- 4) 数据库级最小附加日志,表级 trandata 依赖它 alter database add supplemental log data; -- 5) 12c 及以上才有的开关,11g 执行会报 ORA-02065 alter system set enable_goldengate_replication = true scope=both;

这段里最需要留意的是第 5 条。这条语句是 12.2 之后才引入的,如果源库还是 11.2.0.4,敲下去直接报 ORA-02065 无效选项,不用慌,跳过即可,11g 没有这个开关也能正常抽取。很多照抄脚本的人在这一步以为环境有问题,反复重装,其实只是版本差异。第 4 条执行完必须切一次日志,附加日志才会对后续的 redo 生效:

-- 附加日志对后续 redo 生效 alter system switch logfile; -- 确认结果:两列都应该是 YES select SUPPLEMENTAL_LOG_DATA_MIN, FORCE_LOGGING from v$database;

SUPPLEMENTAL_LOG_DATA_MIN为 YES 表示最小附加日志已开,FORCE_LOGGING为 YES 表示强制日志已开。RAC 环境下alter system switch logfile只切当前实例,换成alter system archive log current更稳妥。另外别忘了看一眼归档空间,抽取进程依赖日志留存,空间满了归档写不进去,抽取会直接卡死:

-- 归档空间水位,超过 80% 就要提前扩容或调整保留策略 select * from v$flash_recovery_area_usage; select name, space_limit/1024/1024 mb_limit, space_used/1024/1024 mb_used from v$recovery_file_dest;

2.2 目标库为什么只做一半:附加日志、force logging 都不是它的事

目标库的角色是“被写入”,它不产生需要被抽取的日志,所以附加日志、表级 trandata、force logging 在目标端统统不需要。这一点是新手最容易做冗余的地方,看到源库脚本就整段复制过去执行,倒也不会报错,但会白白让目标库多写一份补充日志,日志量上涨,恢复和备份成本跟着涨。

真正需要在目标库做的是账号权限和 12c 的那个开关。目标库的复制进程要用 DML 语句往业务表里写数据,因此除了常规的连接、会话权限,还要额外给insert any table, update any table, delete any table。有些环境图省事给了 DBA 角色,测试阶段没问题,上生产之后审计大概率过不去,还是按最小权限来。

配置项Windows 源库Linux 目标库
归档模式必须开启建议开启,便于恢复与闪回
force logging必须开启不需要
数据库级附加日志必须开启不需要
表级 add trandata每张同步表都要加不需要
DML any table 权限不需要必须授予
enable_goldengate_replication12c 及以上必须12c 及以上必须

表里这一行“归档建议开启”不是套话。目标库一旦被误操作,没有归档就只能全量重来,而全量重来的代价是又一次几小时的停机窗口,这笔账怎么算都不划算。

2.3 goldengate 账号:表空间、建用户与 grant_admin_privilege 到底做了什么

两端各建一个专用账号,别用业务用户,也别用 sys。表空间给 300M 起步、自动扩展,checkpoint 表和 trail 元数据都放在这里。建完用户之后有一句关键调用dbms_goldengate_auth.grant_admin_privilege,它一次性把 OGG 需要的那些dbms_*包执行权限、若干v$与dba_视图的查询权限打包授予,比手工一条条 grant 靠谱得多。

-- 源库和目标库都要执行,路径按各自环境改 create tablespace goldengate datafile '/u01/app/oracle/oradata/test1/ogg01.dbf' size 300m autoextend on; create user goldengate identified by goldengate default tablespace goldengate; grant connect, resource, create session, alter session to goldengate; grant flashback any table to goldengate; -- 打包授予 OGG 管理员所需权限 exec dbms_goldengate_auth.grant_admin_privilege('GOLDENGATE'); -- 仅目标库需要:复制进程要能往任意业务表写数据 grant insert any table, update any table, delete any table to goldengate; -- 两端都开,11g 跳过这一句 alter system set enable_goldengate_replication = true scope=both;

flashback any table这个权限容易被忽略。它的用途是当日志里信息不足、或者需要按 SCN 做一致性查询时,OGG 能直接闪回读表。少了它,某些一致性校验场景会失败,报错信息还很不直观。

有一点要提醒:grant_admin_privilege里的用户名必须大写。Oracle 默认用户名大小写不敏感,但这个包的入参是字符串,小写传进去会找不到用户。类似的坑在后面 GLOBALS 文件里的GGSCHEMA也会遇到——那里恰恰要写小写,因为它是实际存储的 schema 名。这两种写法不一致,是很多人第一次部署时反复卡住的地方。

2.4 上线前自检:三条 SQL 加一个视图

配置做完不要急着装软件,先把这几项确认一遍,能省掉后面大量排查时间。自检的核心是确认“日志真的能抽”,而不是“我以为开了”。

-- 1) 归档与附加日志状态 select log_mode, SUPPLEMENTAL_LOG_DATA_MIN, FORCE_LOGGING, SUPPLEMENTAL_LOG_DATA_PK, SUPPLEMENTAL_LOG_DATA_UI from v$database; -- 2) 12c 参数是否生效 show parameter enable_goldengate_replication; -- 3) 账号权限是否被正确授予 select * from dba_goldengate_privileges where grantee = 'GOLDENGATE';

第三条查的是dba_goldengate_privileges,这个视图能直接看到grant_admin_privilege到底授了哪些权限。如果视图查出来是空的,说明那句 exec 没执行成功,或者用户名传成了小写。源库 Windows 侧还要顺手确认归档目标路径所在磁盘的剩余空间,跨平台同步的日志量往往比预估的大,尤其是首次全量期间,抽取进程并发读日志,归档生成速度会明显上升。

3. 两端安装与 GGSCI 初始化:Windows 图形安装、Linux 静默解压、MGR 参数一行都别省

安装这一步本身不难,难点在于两端的环境差异:Windows 那边是图形界面加服务注册,Linux 这边是解压加图形安装器,中间还夹着目录权限、环境变量和端口。我一般会把这一步拆成“装软件、建目录、配全局参数、起 MGR、验端口”五件事,做完一件验一件,别攒到最后一起调。

3.1 Windows 源端:图形安装、安装目录与 MGR 服务注册

Windows 上的 OGG 介质是压缩包,解压后进Disk1目录运行安装程序,图形界面里要选对两件事:一是目标数据库版本,必须和本机ORACLE_HOME对应的版本一致,选错了后面连库会报库版本不匹配;二是安装目录,路径里不要有空格、中文和特殊字符,我见过装在D:\Program Files\ogg下面,结果参数文件里的路径被空格截断,进程起不来的情况。

安装完成后用命令行进到安装目录启动 GGSCI,第一件事是建子目录:

# Windows 命令行,进入 OGG 安装目录 cd /d D:\ogg GGSCI # GGSCI 内部执行,创建 dirprm/dirdat/dirrpt 等标准子目录 GGSCI> create subdirs

create subdirs会在当前目录下建出一整套标准目录结构,dirprm放参数文件、dirdat放 trail 文件、dirrpt放报告、dirchk放检查点。这一步两端都必须做,漏了后面所有edit params都会失败。

Windows 端还有一个容易被忽略的动作:把 MGR 注册成系统服务。如果只是前台start mgr,机器一重启抽取就停了,而目标端复制进程还在正常跑,表面上一切正常,实际上延迟已经悄悄涨到几十小时。

# 在 GGSCI 里把 MGR 注册为 Windows 服务,随机器启动 GGSCI> install add service

注册成服务之后,MGR 的运行身份要确认清楚,建议用专用的系统账号而不是随便一个登录用户,否则改密码之后服务起不来。

3.2 Linux 目标端:解压、runInstaller 与数据库版本对应关系

Linux 这一侧是标准的解压加图形安装流程。用 oracle 用户操作,不要用 root 装完再改属主,权限问题会在后面以各种奇怪的方式冒出来。

# 切换到 oracle 用户,解压安装介质 su - oracle unzip 122022_fbo_ggs_Linux_x64_shiphome.zip # 进入 Disk1 目录执行安装器 cd fbo_ggs_Linux_x64_shiphome/Disk1 ./runInstaller

runInstaller是图形界面,需要 DISPLAY 可用或者用 X11 转发。界面里最关键的一项同样是数据库版本选择,它决定了 OGG 链接哪一套客户端库。选完之后指定安装目录,一般放/u01/app/ogg,安装器会自动把LD_LIBRARY_PATH相关配置写进环境脚本。

装完补一下环境变量,写进 oracle 用户的.bash_profile,否则每次开新会话都要手工 export:

# 追加到 ~/.bash_profile export GG_HOME=/u01/app/ogg export PATH=$GG_HOME:$PATH export LD_LIBRARY_PATH=$GG_HOME:$LD_LIBRARY_PATH

装完之后同样进 GGSCI 执行create subdirs。如果执行时报目录已存在,说明这个目录之前装过 OGG,要么复用要么彻底清干净,别在半残留的目录上继续配,检查点文件残留会导致新进程起来就报错。

3.3 GLOBALS、checkpoint 表与 MGR 进程参数

GLOBALS 是全局参数文件,两端都要配,位置在 OGG 安装目录下,文件名就叫GLOBALS,没有后缀。它定义三件事:OGG 用哪个 schema 存元数据、检查点表叫什么、要不要写系统日志。

# GGSCI 内执行,两端一致 GGSCI> edit params ./GLOBALS

文件内容三行:

GGSCHEMA goldengate CHECKPOINTTABLE goldengate.ggschkpt SYSLOG NONE

GGSCHEMA这里写小写,是因为它对应数据库中实际的 schema 名;而前面grant_admin_privilege('GOLDENGATE')要大写,是因为那是作为字符串参数传入的。这个大小写的不对称是 OGG 部署里最经典的一处不一致,配错了表现是 GGSCI 登录成功但一加检查点就报找不到表。

接着登录数据库并创建检查点表:

# 用 goldengate 账号登录数据库 GGSCI> dblogin userid goldengate password goldengate # 在数据库里创建检查点表,两端都要做 GGSCI> add checkpointtable goldengate.ggschkpt

检查点表记录的是每个进程读到哪个位置、写到哪个位置,是断点续传的依据。它丢了,复制进程就不知道该从哪儿接着来,只能重头扫 trail 文件。

MGR 是管理进程,负责拉起其他进程、分配动态端口、清理过期 trail。参数里几行值得逐个讲:

# GGSCI> edit params mgr PORT 7809 DYNAMICPORTLIST 7800-7810 USERID goldengate, PASSWORD goldengate AUTORESTART ER *, RETRIES 3, WAITMINUTES 5, RESETMINUTES 60 LAGREPORTMINUTES 10 LAGCRITICALMINUTES 10 PURGEOLDEXTRACTS ./dirdat/*, USECHECKPOINTS, MINKEEPHOURS 12 PURGEDDLHISTORY MINKEEPDAYS 7, MAXKEEPDAYS 14, FREQUENCYHOURS 3 PURGEMARKERHISTORY MINKEEPDAYS 7, MAXKEEPDAYS 14, FREQUENCYHOURS 3

PORT 7809是 MGR 的固定监听端口,DataPump 进程用RMTHOST ... MGRPORT 7809连过来,所以两端这个端口必须一致且可达。DYNAMICPORTLIST是实际传数据的端口范围,MGR 会从这个区间里挑一个给传输用——只开 7809 不开这段范围,是跨机器部署最常见的“连上了但传不动”的原因。AUTORESTART让进程异常退出后自动拉起,重试 3 次、间隔 5 分钟、60 分钟后重置计数,避免进程疯狂重启刷日志。PURGEOLDEXTRACTS控制 trail 清理,MINKEEPHOURS 12表示至少保留 12 小时,这个值要和你的最大故障恢复窗口匹配,配小了出事时想重放都没有文件。

3.4 跨机器必须打通的端口与连通性验证

Windows 源端到 Linux 目标端,方向是源端主动连目标端,所以要通的是目标端的 7809 加动态端口段。验证别只用 ping,ping 通不代表端口通。

# Linux 侧确认 MGR 在监听 netstat -anp | grep 7809 # Windows 侧测试目标端端口(PowerShell) Test-NetConnection 10.0.100.141 -Port 7809

如果 7809 通但动态端口段被防火墙挡了,现象会非常迷惑:DataPump 进程状态是 RUNNING,info datapump看不到报错,但目标端dirdat目录里始终不出现新文件。这时候去看ggserr.log,一般能找到重试连接的记录。所以规划阶段就把整段端口一起放行,别只放一个 7809。

4. 抽取、投递、复制三条进程:参数逐行拆开配,初始化按 SCN 对齐

进程配置是这套方案的主体。源端两个进程(Extract 抽日志、DataPump 传文件),目标端一个进程(Replicat 应用数据),三条链路串起来。参数文件不是越长越好,但每个参数背后都对应一个具体故障场景,配的时候要知道它在防什么。

4.1 源端 DDL 支持:marker_setup、ddl_setup 与 add trandata

如果只同步 DML,这一段可以跳过;但只要业务会加字段、建索引,就必须配。DDL 同步依赖几个官方脚本,在源端用 sysdba 依次执行:

-- 源端 sysdba 执行,顺序不能乱 grant execute on utl_file to goldengate; @/u01/app/ogg/marker_setup @/u01/app/ogg/ddl_setup @/u01/app/ogg/role_setup GRANT GGS_GGSUSER_ROLE TO goldengate; @/u01/app/ogg/ddl_enable -- 提高 DDL 复制性能,参数是 OGG 管理员的 schema 名 @?/rdbms/admin/dbmspool.sql @/u01/app/ogg/ddl_pin goldengate

marker_setup建的是 DDL 标记表,用来在 redo 里定位 DDL 语句;ddl_setup建历史表和触发器;role_setup建角色。三个脚本都要求用 sysdba 跑,用普通账号会中途报权限不足。

然后是表级附加日志。这一步决定 OGG 能不能拿到行级的完整前镜像:

# GGSCI 内,登录后逐表添加 GGSCI> dblogin userid goldengate password goldengate GGSCI> add trandata test.t1

add trandata有个硬性前提:表上必须有主键或唯一索引。没有的话命令会直接拒绝,这时候要么补主键,要么显式指定列作为替代键。替代键的作用是过滤重复行,选错了会出现更新丢失,选列的原则是能唯一标识一行且更新频率低。

4.2 Extract 进程:从 redo 里抽增量写到本地 trail

Extract 是源端的第一个进程,读 redo 或归档日志,把变更写成 trail 文件。参数如下:

# GGSCI> edit param extgsxf EXTRACT extgsxf SETENV (ORACLE_HOME="/u01/app/oracle/product/11.2.0/db_1") SETENV (ORACLE_SID="test1") SETENV (NLS_LANG="AMERICAN_AMERICA.AL32UTF8") USERID goldengate, PASSWORD goldengate EXTTRAIL ./dirdat/gs TRANLOGOPTIONS LOGRETENTION DISABLED BRINTERVAL 20M TRANLOGOPTIONS BUFSIZE 2048000 GETREPLICATES CACHEMGR CACHESIZE 2GB GETTRUNCATES DDL INCLUDE MAPPED, OBJTYPE 'TABLE' & INCLUDE MAPPED OBJTYPE 'INDEX' DDLOPTIONS ADDTRANDATA RETRYOP RETRYDELAY 10 MAXRETRIES 10 DDLOPTIONS REPORT DISCARDFILE ./dirrpt/extgsxf.dsc, APPEND, MEGABYTES 1000 DISCARDROLLOVER AT 6:00 REPORTROLLOVER AT 6:00 REPORTCOUNT EVERY 1 HOURS, RATE FETCHOPTIONS FETCHPKUPDATECOLS REPORT AT 0:01 FETCHOPTIONS MISSINGROW ABEND STATOPTIONS REPORT FETCHWARN LONGTRANS 1H, CHECKINTERVAL 10m DYNAMICRESOLUTION TABLE test.*;

几处关键点。SETENV里三行缺一不可,ORACLE_HOME写错进程起不来,ORACLE_SID写错连到别的库,NLS_LANG不一致会导致中文变成问号——这是跨平台同步里非常高频的一个翻车点。LOGRETENTION DISABLED表示不依赖 OGG 自己管理日志保留,交给数据库的归档策略,配了它就要确保归档保留时间够长。CACHEMGR CACHESIZE 2GB是大事务的缓冲,遇到一次性更新几十万行的批处理,缓存给小了会报长事务告警甚至中断。LONGTRANS 1H是长事务阈值,超过一小时就告警,配合CHECKINTERVAL 10m每十分钟检查一次。GETTRUNCATES让 truncate 也能同步过去,不放这个参数的话目标端会留着已经被清空的数据。FETCHOPTIONS MISSINGROW ABEND是我强烈建议保留的一行——遇到找不到行的情况直接中止而不是跳过,跳过意味着数据静默不一致,比报错可怕得多。

配完参数后注册进程并启动:

GGSCI> add extract extgsxf tranlog, begin now GGSCI> add exttrail ./dirdat/gs, extract extgsxf, megabytes 1024 GGSCI> start extgsxf

megabytes 1024是单个 trail 文件的大小,太大回放粒度粗,太小文件数量多、管理麻烦,1G 是个比较稳的折中。

4.3 DataPump 进程:把 trail 文件投递到对端

DataPump 不做任何数据转换,只负责搬运,所以参数很短:

# GGSCI> edit param dpgskf EXTRACT dpgskf PASSTHRU DYNAMICRESOLUTION RMTHOST 10.0.100.141, MGRPORT 7809 RMTTRAIL ./dirdat/gs DISCARDFILE ./dirrpt/dpgskf.dsc, APPEND, MEGABYTES 100 DISCARDROLLOVER AT 6:00 REPORTROLLOVER AT 6:00 REPORTCOUNT EVERY 1 HOURS, RATE TABLE test.*;

PASSTHRU表示不做数据库层面的转换,这是 DataPump 的标准写法,加了它才能不依赖本地数据库连接。RMTHOST后面跟目标端 IP 和 MGR 端口,注意这里填的是 MGR 端口不是动态端口,动态端口由 MGR 协商分配。

GGSCI> add extract dpgskf, exttrailsource ./dirdat/gs GGSCI> add RMTTRAIL ./dirdat/gs, extract dpgskf, megabytes 1024 GGSCI> start dpgskf

exttrailsource指向本地读取位置,RMTTRAIL指向远端写入位置,两个名字可以一样但概念不同,配反了进程起不来。

4.4 Replicat 进程:在目标端把 trail 还原成 SQL

Replicat 是唯一真正往目标库写数据的进程:

# GGSCI> edit param repgs1 REPLICAT repgs1 SETENV (ORACLE_HOME = "/u01/app/oracle/product/11.2.0/db_1") SETENV (ORACLE_SID = "test1") SETENV (NLS_LANG = "AMERICAN_AMERICA.AL32UTF8") USERID goldengate, PASSWORD goldengate ASSUMETARGETDEFS DBOPTIONS DEFERREFCONST DBOPTIONS SUPPRESSTRIGGERS DISCARDFILE ./dirrpt/repgs1.dsc, APPEND, MEGABYTES 1000 DISCARDROLLOVER AT 6:00 REPERROR (DEFAULT, ABEND) DDL INCLUDE MAPPED, OBJTYPE 'TABLE' & INCLUDE MAPPED OBJTYPE 'INDEX' DDLOPTIONS REPORT REPORTROLLOVER AT 6:00 REPORTCOUNT EVERY 30 MINUTES, RATE REPORT AT 0:01 STATOPTIONS RESETREPORTSTATS NUMFILES 150 GETTRUNCATES DYNAMICRESOLUTION ALLOWNOOPUPDATES GROUPTRANSOPS 1000 MAP test.*, TARGET test.*;

ASSUMETARGETDEFS表示两端表结构完全一致,不再去读源端定义文件。跨平台同步时这个假设要成立——Windows 和 Linux 上表的列类型、长度、字符集必须对得上,对不上就得改成SOURCEDEFS方式并生成定义文件,那是另一套流程。DBOPTIONS SUPPRESSTRIGGERS抑制目标端触发器,避免同步写入再触发一次业务逻辑造成数据翻倍。GROUPTRANSOPS 1000把最多 1000 条操作合并成一个事务提交,是吞吐和回放粒度之间的权衡,调大提升性能但故障时重放的数据量更大。REPERROR (DEFAULT, ABEND)表示除明确忽略的错误外一律中止,这和前面抽取端的MISSINGROW ABEND是同一个思路:宁可停下来查,不要静默跳过。

GGSCI> add replicat repgs1, exttrail ./dirdat/gs, checkpointtable goldengate.ggschkpt

4.5 初始化数据:SCN 对齐、expdp 与 sourceistable 两种打法

增量链路配好之后,还差最后一块:存量数据。逻辑是取一个 SCN 作为分界点,该点之前的数据用导出导入搬,该点之后的增量交给 OGG 重放。分界点取错,就会出现主键冲突或者数据空洞。

-- 在源库取当前 SCN 作为一致性点 select to_char(current_scn) from v$database; -- 按该 SCN 导出,保证导出内容与增量衔接 expdp test/test TABLES=test.t1 DUMPFILE=t1.dmp flashback_scn=1085057

导出文件拷到目标端后导入,然后复制进程从这个 SCN 之后开始:

# 目标端启动复制进程,从指定 SCN 之后开始应用 GGSCI> start replicat repgs1, aftercsn 1085057

另一种做法是不落文件,直接用sourceistable做初始化抽取,适合表不大、想省掉导出导入环节的场景。源端加一个特殊抽取进程:

GGSCI> add extract init_t1, sourceistable GGSCI> edit params init_t1
EXTRACT init_t1 USERID goldengate, PASSWORD goldengate RMTHOST 10.0.100.141, MGRPORT 7809 RMTFILE ./dirdat/i1, maxfiles 999, megabytes 500 TABLE test.t1, SQLPREDICATE 'AS OF SCN 1085057';

目标端配一个specialrun复制进程直接消费这个文件:

GGSCI> add replicat ri1, specialrun GGSCI> edit params ri1
SPECIALRUN END RUNTIME REPLICAT ri1 USERID goldengate, PASSWORD goldengate EXTFILE ./dirdat/i1 MAP test.t1, TARGET test.t1;

启动顺序是:先开常规抽取和投递,再跑初始化抽取,然后前台执行一次./replicat paramfile dirprm/ri1.prm完成存量装载,最后start replicat rp1, aftercsn <同一个SCN>。这个顺序错了,会出现增量先应用、存量后覆盖的倒挂。

4.6 进程状态观测:info all 与 ggserr.log

进程起来之后,日常就看两个地方。一是info all,看三个进程是否 RUNNING、延迟多少:

GGSCI> info all GGSCI> info extract extgsxf, detail GGSCI> info replicat repgs1, detail

detail里能看到当前读到的 RBA、序列号、最后一条操作时间,延迟异常时对比源端和目标端的 RBA 位置,就能判断卡在抽取、传输还是应用。二是ggserr.log,在 OGG 安装目录下,所有进程的启停和报错都记在这里,出问题第一件事就是tail -f它。

5. 跨平台同步的避坑记录:五个把我卡到凌晨的现象与解法

这一节写的都是实际踩过的,不是从手册上抄的。每条按“看到什么、为什么、怎么解”来说,遇上了能直接对上号。

5.1 现象:Extract 启动几秒就 ABENDED,报找不到 redo 或 ORA-01291

原因:归档没开、附加日志没生效、或者开关改完没切日志。还有一种情况是数据库刚做完大批量 nologging 操作,那段时间的 redo 里根本没有行数据。

解决:先查v$database的LOG_MODE和SUPPLEMENTAL_LOG_DATA_MIN,两个都要 YES;再确认改完配置后执行过alter system switch logfile。如果是 nologging 造成的历史空洞,只能对相关表重新做一次全量初始化,增量补不回来。

5.2 现象:Replicat 报 ORA-00001 唯一约束冲突,进程反复中止

原因:初始化 SCN 和aftercsn没对齐。导出用的 SCN 是 1085057,复制却从更早的位置开始,同一批 insert 被应用了两遍;或者反过来,导出用了较晚的 SCN,增量却从更早开始,中间一段既不在导出文件里也没被重放。

解决:导出的flashback_scn和start replicat的aftercsn必须是同一个值,抄的时候别抄错一位。真出了冲突,用REPERROR临时跳过只会让不一致扩散,正确做法是清掉目标表、重新按统一 SCN 做一次初始化。

5.3 现象:目标端中文变成问号,或者插入时报字符长度超限

原因:两端NLS_LANG不一致,或者源库是 ZHS16GBK、目标库是 AL32UTF8,同一列在 UTF-8 下字节长度翻倍。Windows 源端的默认字符集和 Linux 目标端往往不同,这是跨平台同步特有的问题。

解决:两端SETENV (NLS_LANG=...)统一写成AMERICAN_AMERICA.AL32UTF8,同时在设计阶段就把 varchar2 列按字节语义检查一遍,必要时扩长度或者改成VARCHAR2(x CHAR)。这个问题在测试阶段用英文数据测不出来,一定要用真实中文样本验证。

5.4 现象:DataPump 显示 RUNNING,但目标端 dirdat 目录一直不出现新文件

原因:7809 端口通了,DYNAMICPORTLIST那段范围被防火墙或者安全组挡了。MGR 协商出来的传输端口连不上,进程会不停重试,状态看起来正常。

解决:把动态端口段整体放行,别只开 7809;验证时用目标端netstat观察实际建立的连接端口,再回源端测同端口连通性。ggserr.log里通常有连接重试的记录,只是不会以 ERROR 级别出现,容易被忽略。

5.5 现象:Replicat 报找不到 trail 文件,或者文件序号跳变

原因:MGR 的PURGEOLDEXTRACTS清理太激进,MINKEEPHOURS设得太小,复制进程还没消费完的文件就被删了;也可能是目标端 MGR 起来之前,源端就开始投递,文件落在了错误的位置。

解决:MINKEEPHOURS至少覆盖你的最大故障恢复窗口,我这个环境设的 12 小时;启动顺序上先起目标端 MGR 再起源端投递。已经丢了文件的,只能按最后一个成功的检查点重新初始化,没有别的捷径。

6. 上线之后怎么确认真的同步对了:三条验证与一个延迟定位习惯

进程全绿不等于数据对。我一般在上线当天做三组验证:结构、存量、增量。结构比dba_tab_columns的行数和关键列类型;存量比count(*)和主键max/min;增量则是手工造三类操作——insert、update、delete,再加一次 truncate——逐条到目标端核对。

最省事的做法是写一条对账 SQL,两端各跑一次比对结果:

-- 两端分别执行,比对行数与主键区间 select 'T1' tab, count(*) cnt, min(object_id) min_id, max(object_id) max_id from test.t1;

日常巡检我固定看三个指标,按这个顺序查基本能定位到卡在哪一段:

检查项命令正常表现异常指向
抽取延迟info extract extgsxf, detail延迟秒级源库日志生成过快或归档空间不足
传输状态info extract dpgskf, detail目标端文件持续增长网络或动态端口问题
应用延迟info replicat repgs1, detail延迟与抽取接近目标端锁冲突或大事务

有一回目标端延迟涨到 40 分钟,info replicat显示进程一直在跑,最后是在报告文件里看到某个大更新卡在了行锁上——业务侧有个未提交的长事务占着同一批行。从那以后我每次上线都强制走一遍“延迟三段对比”:先看抽取端 RBA 有没有追上最新归档,再看传输端目标文件是否持续增长,最后看应用端最后一条操作时间。三段里哪一段停住,问题就在那一段,不用全链路瞎猜。

跨平台这套链路,真正难的不是装软件,而是让“配置生效”这件事可验证。开关改完切日志、进程起来看 detail、初始化对齐同一个 SCN、上线后三段对延迟,这几步做扎实,Windows 到 Linux 的同步就能稳稳跑住。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表