简介:《Oracle OGG安装部署细说:Windows同步到Linux》是一份面向Oracle DBA、数据同步实施人员及异构环境运维者的PDF技术文档,聚焦Windows端Oracle到Linux端Oracle的GoldenGate实时复制部署。内容围绕源库与目标库准备、归档与强制日志及附加日志开启、OGG专用用户与权限授予、enable_goldengate_replication参数设置、ggsci子目录初始化、GLOBALS与checkpoint表配置,以及Manager、Extractor、Replicat组件配置和后续监控维护、日志排查展开,附有可直接参考的SQL与命令片段。压缩包仅含1个PDF文件,大小约496KB,便于随身查阅和按步骤对照实施。目前已有298人学习,适合需要快速搭建OGG同步链路、梳理跨操作系统部署要点或查漏补缺的初中级读者。
1. 跨平台同步先想清楚三件事:OGG 12.2 的适用边界
上周有位同行问我,Windows 上的业务库要并到 Linux 那套新环境,两边得同时写一段时间,问有没有比写触发器更靠谱的做法。这种 oracle linux OGG 数据同步的场景,GoldenGate 基本是绕不开的选项——它从源库的在线 redo 或归档里抓变更,落成自己的 trail 文件,再投递到目标端重放,中间不碰源库的业务表,源端压力可控,目标端还能做字段映射和冲突策略。这次拆的是一份 OGG 12.2.0.2 的部署记录,源头是 Windows 上的 Oracle,目标端是 Linux 上的 Oracle,跨操作系统、跨字符集,链路里该踩的坑一个不少。适合手上正要做异构迁移、双写过渡或者报表库准实时同步的人,尤其是第一次从零配 Extract / DataPump / Replicat 三进程的。下面按数据库前置条件、安装初始化、三进程配置、初始化数据对齐、排错的顺序,把这条链路完整走一遍。
2. 数据库侧前置条件:归档、强制日志与附加日志的四个开关
OGG 能不能跑起来,一半取决于数据库这边开没开对。很多进程起不来的问题,根子不在 OGG 参数,而在源库压根没记全所需的信息。这一章把源库和目标库要改的东西一次列清,顺序也别乱,先开归档再谈附加日志。
2.1 源库三个开关的顺序与验证
源库必须处于归档模式,Extract 读的是在线 redo,归档是它的兜底。如果 Extract 停了一段时间再启动,需要回头去读归档,库不在归档模式就只能重新做初始化。切换归档要重启到 mount 状态:
-- 以 sysdba 身份连接源库 SQL> shutdown immediate; SQL> startup mount; SQL> alter database archivelog; SQL> alter database open; -- 强制记录日志:保证即使表上开了 nologging,变更也会写 redo SQL> alter database force logging; -- 开启最小附加日志,让 redo 里带上足够定位行的信息 SQL> alter database add supplemental log data; -- 验证三个开关的实际状态 SQL> select SUPPLEMENTAL_LOG_DATA_MIN, FORCE_LOGGING, LOG_MODE from v$database;逻辑说明:force logging是必须的,业务方偶尔为了赶批量会临时改成 nologging,一旦发生,这部分变更在 redo 里就是残缺的,Replicat 端会出现行对不上。add supplemental log data打开的是库级最小附加日志,配合后面表级的add trandata才能真正把主键或唯一索引的前镜像写进去。
参数说明:SUPPLEMENTAL_LOG_DATA_MIN期望值是YES,如果显示IMPLICIT说明只开了最小集合,需要再确认表级 trandata 是否加过。执行完这三个开关后,建议手动切一次日志让配置立即生效,不用等自然切换:
SQL> alter system switch logfile;这一步别省。有次我在测试库上开完附加日志就去加 trandata,结果报找不到补充日志信息,切了一次日志就正常了,属于典型的"配置生效滞后"。
2.2 OGG 账号:表空间、系统权限与 dbms_goldengate_auth
OGG 需要一个独立的数据库账号,源端和目标端都要建,且权限不完全一样。别图省事用 sys 或 system,checkpoint 表和 trail 元数据都会写进这个账号下,混用之后清理起来很麻烦。
-- 建独立表空间,300M 起步,自动扩展 SQL> create tablespace goldengate 2 datafile '/u01/app/oracle/oradata/test1/ogg01.dbf' 3 size 300m autoextend on; -- 建账号 SQL> create user goldengate identified by goldengate 2 default tablespace goldengate; -- 基础权限 SQL> grant connect, resource, create session, alter session to goldengate; -- 允许闪回查询,日志信息不足时用 as of scn 补查 SQL> grant flashback any table to goldengate; -- 关键一步:授予 OGG 管理员所需的一套内部权限 SQL> exec dbms_goldengate_auth.grant_admin_privilege('GOLDENGATE'); -- 打开 OGG 复制开关,12c 之后必须显式开启 SQL> alter system set enable_goldengate_replication = true scope=both;逻辑说明:dbms_goldengate_auth.grant_admin_privilege这个包会一次性授予 OGG 需要的几十个内部权限,包括读 redo、管队列、操作 checkpoint 表等。手工一条条 grant 极容易漏,漏了之后的报错往往很含糊,比如ORA-26903或者进程启动即 ABEND。我一般习惯把它当成建号的标准动作,跟create user连着写。
参数说明:第二个参数可以传*表示对所有 schema 生效,也可以只传具体用户名。传具体用户名更安全,避免 OGG 账号有能力去碰不该碰的库。enable_goldengate_replication是实例级参数,scope=both保证重启后依然有效,别只写memory。
2.3 目标库少开什么、多开什么
目标库是接收端,不需要从自己的 redo 里抽数据,所以归档和附加日志都可以不开(除非目标端还要往下游再同步一层)。但账号权限要补两块:一是前面那套建号流程一模一样走一遍,二是额外给 DML 权限。
-- 目标库建号部分与源库一致,此处略过,补充 DML 授权 SQL> grant insert any table, update any table, delete any table to goldengate; -- 目标库同样要打开复制开关 SQL> alter system set enable_goldengate_replication = true scope=both;逻辑说明:Replicat 是以 OGG 账号身份往目标表里写数据的,如果只给了 connect/resource,遇到跨 schema 的MAP test.*, TARGET test.*就会报权限不足。用insert any table这类系统权限是为了省掉逐表授权的活,如果安全策略不允许,也可以改成对象级授权,但表一多就很痛,我一般倾向于前者。
目标库还有个容易忽略的点:checkpoint 表要单独建在目标库里,不能跟源库共用。源端和目标端的 checkpoint 表结构相同、数据独立,各自记录自己进程的读写位置。两边都执行add checkpointtable goldengate.ggschkpt即可,这个动作放在下一章的 GGSCI 初始化里做更顺手。
3. OGG 安装与两端初始化:Windows 与 Linux 的差异点
安装本身不复杂,麻烦的是两端目录结构、环境变量、服务注册方式都不一样。这一章先把安装落盘讲清楚,再把create subdirs、GLOBALS、checkpoint 表、MGR 参数这几步做完,做完之后两端应该都能start mgr成功。
3.1 安装包与 runInstaller 的落盘路径
Linux 端的安装包是122022_fbo_ggs_Linux_x64_shiphome.zip,用 oracle 用户解压后进入fbo_ggs_Linux_x64_shiphome/Disk1执行runInstaller,图形界面里选择与源库匹配的数据库版本,安装路径我一般固定成/u01/app/ogg,跟 Oracle 的 ORACLE_BASE 分开,备份和清理都方便。
# 切到 oracle 用户再操作,别用 root 解压 su - oracle unzip 122022_fbo_ggs_Linux_x64_shiphome.zip cd fbo_ggs_Linux_x64_shiphome/Disk1 export DISPLAY=10.0.100.21:0.0 # 图形化安装需要 ./runInstaller逻辑说明:runInstaller是 Java 写的图形安装器,没有 X 转发会直接报错退出。如果服务器不给开图形,也可以选静默安装,用 response file,但 12.2 的 response 模板生成比较绕,第一次部署时用图形界面确认一遍路径和组件更稳妥。
参数说明:安装路径里不要带空格和中文,Windows 端同理。Windows 端的包是fbo_ggs_Windows_x64_shiphome.zip,解压后跑setup.exe,装到C:\ogg。装完两端都要确认ggsci能起来,这是后面所有命令的入口。
3.2 create subdirs 与 GLOBALS 的三个参数
安装完第一件事是建子目录,它会把 dirprm、dirrpt、dirdat、dirchk 这些工作目录一次建好,源端目标端都要做。
[oracle@test1 ogg]$ ./ggsci Oracle GoldenGate Command Interpreter for Oracle Version 12.2.0.2.2 OGGCORE_12.2.0.2.0_PLATFORMS_170630.0419_FBO Linux, x64, 64bit (optimized), Oracle 11g on Jun 30 2017 14:42:26 GGSCI (test1) 1> create subdirs接着配全局参数文件。GLOBALS 是个无扩展名的纯文本文件,放在 OGG 安装根目录下,源端目标端内容一致:
GGSCI (test1) 2> edit params ./GLOBALS GGSCHEMA goldengate CHECKPOINTTABLE goldengate.ggschkpt SYSLOG NONE逻辑说明:GGSCHEMA告诉 OGG 用哪个 schema 存内部对象,CHECKPOINTTABLE指定 checkpoint 表的全名,写上这两个之后,后面建进程时就不需要反复指定 checkpoint 表。SYSLOG NONE是关掉往系统日志写消息,Linux 上如果不关,/var/log/messages会被 OGG 刷得很难看。
参数说明:文件名必须叫GLOBALS,大写,没有后缀,放在 OGG 根目录。改了之后要重启 MGR 才生效。Windows 端路径是C:\ogg\GLOBALS,用记事本存成 ANSI 或 UTF-8 无 BOM 都行,带 BOM 会解析失败。
3.3 checkpoint 表与 MGR 进程参数逐行拆解
先登录数据库,再建 checkpoint 表,两端都做:
GGSCI (test1) 3> dblogin userid goldengate password goldengate Successfully logged into database. GGSCI (test1 as goldengate@test1) 4> add checkpointtable goldengate.ggschkpt Successfully created checkpoint table goldengate.ggschkpt.MGR 是管理进程,负责启动、监控、自动重启其他进程,也是 DataPump 投递的目标端口。参数文件长这样:
GGSCI (test1) 5> 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是 MGR 的固定监听端口,DYNAMICPORTLIST是给 DataPump 动态分配的端口范围。中间是自愈配置,AUTORESTART ER *表示任何进程异常退出都自动拉起,最多重试 3 次,每次间隔 5 分钟,60 分钟后计数清零。后面三行是清理策略,trail 文件、DDL 历史、marker 历史分别按小时和天保留,USECHECKPOINTS保证只删已经确认消费完的文件。
参数说明:MINKEEPHOURS 12是我习惯留的缓冲,给排错留出回看窗口,如果磁盘紧张可以压到 4 小时。LAGCRITICALMINUTES 10会往 ggserr.log 里写严重延迟告警,配合监控抓取很方便。密码明文写在参数文件里不符合安全审计要求,正式环境建议改用credentialstore加别名,这里为了步骤清晰先保持明文。
GGSCI (test1 as goldengate@test1) 6> start mgr Manager started.两端都start mgr成功后,info mgr应该能看到运行状态和端口。到这一步,两端的基础骨架就搭好了,接下来才是真正配链路。
4. 三进程链路与初始化数据:Extract、DataPump、Replicat 怎么串起来
OGG 的链路是三个进程接力:源端 Extract 读 redo 写本地 trail,源端 DataPump 读本地 trail 投递到目标端,目标端 Replicat 读远程 trail 重放到目标表。三者职责不同,参数侧重点也不同,配错任何一环,数据就断在半路。
4.1 源端 Extract:从在线 redo 里抓变更
先加表级附加日志,再建 Extract。表级 trandata 是必须的,只有库级最小附加日志不够,Replicat 定位不到具体行。
GGSCI (test1) 7> dblogin userid goldengate password goldengate GGSCI (test1 as goldengate@test1) 8> add trandata test.t1Extract 参数文件:
GGSCI (test1) 9> edit params 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 BR 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 FETCHOPTIONS MISSINGROW ABEND STATOPTIONS REPORT WARNLONGTRANS 1H, CHECKINTERVAL 10m DYNAMICRESOLUTION TABLE test.*;逻辑说明:SETENV三行是给 Extract 进程本身指定运行环境,跨平台场景下这三个值尤其关键,NLS_LANG必须跟源库字符集匹配,否则中文表名和字段会在 trail 里变成乱码。TRANLOGOPTIONS LOGRETENTION DISABLED表示不用 OGG 自己的日志保留机制,依赖数据库的归档保留策略,配合BR BRINTERVAL 20M做 Bounded Recovery,进程异常时的恢复粒度控制在 20 分钟内。GETREPLICATES和GETTRUNCATES分别捕获复制语句和 truncate 操作,后者不打开的话目标端会静默丢 DDL 级的清表。DDLOPTIONS ADDTRANDATA让 OGG 在遇到新表时自动加 trandata,省掉人工补。
参数说明:WARNLONGTRANS 1H是长事务告警阈值,超过 1 小时未提交的事务会往日志里写警告,同时CHECKINTERVAL 10m每 10 分钟检查一次。长事务是 trail 膨胀的头号原因,尤其 Windows 端那种批量 job,一定要盯着。FETCHOPTIONS MISSINGROW ABEND表示如果重放时找不到对应行,直接终止进程而不是继续,宁可停下来让人看,也不要带着不一致往下跑。
GGSCI (test1) 10> add extract extgsxf tranlog, begin now EXTRACT added. GGSCI (test1) 11> add exttrail ./dirdat/gs, extract extgsxf, megabytes 1024 EXTTRAIL added. GGSCI (test1) 12> start extgsxfbegin now表示从现在的位置开始抓,如果要做历史数据同步,这里要改成具体 SCN 或用sourceistable方式,第 4.5 节会讲。
4.2 DataPump:跨平台投递与 RMTHOST 的写法
DataPump 跑在源端,把本地 trail 通过网络推到目标端的 MGR 端口。它是最容易被忽略的一环,因为它不出现在数据抽取和重放的逻辑里,但链路断了往往最先断在这。
GGSCI (test1) 13> edit params 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 不做任何过滤和转换,原样转发。加了这个之后TABLE test.*只是个声明,实际投递内容不受影响。RMTHOST写目标端 IP 和 MGR 端口,注意这里是 MGR 的固定端口 7809,不是前面配的 DYNAMICPORTLIST,MGR 收到连接后会分配动态端口给实际的数据流。RMTTRAIL是目标端落盘的 trail 路径,写相对路径即可,OGG 会解析到目标端的安装目录下。
参数说明:跨平台投递时目标端防火墙要放通 7809 以及 7800-7810 这一段。有次在客户现场调了半小时,最后发现是安全组只开了 7809,动态端口被封,表现是 DataPump 状态RUNNING但目标端一直收不到文件,属于很典型的黑匣子式故障。
GGSCI (test1) 14> add extract dpgskf, exttrailsource ./dirdat/gs EXTRACT added. GGSCI (test1) 15> add rmttrail ./dirdat/gs, extract dpgskf, megabytes 1024 RMTTRAIL added. GGSCI (test1) 16> start dpgskf4.3 目标端 Replicat:冲突处理与批量提交
Replicat 在 Linux 端跑,读投递过来的 trail,按 MAP 规则写进目标表。参数里最需要琢磨的是冲突处理和提交粒度。
GGSCI (test2) 17> edit params repgs1 REPLICAT repgs1 SETENV (ORACLE_HOME = "/u01/app/oracle/product/11.2.0/db_1") SETENV (ORACLE_SID = "test2") 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表示源端和目标端表结构一致,不需要额外的定义文件,跨平台但同构的场景用这个最省事。DBOPTIONS DEFERREFCONST把外键约束检查推迟到事务提交时,避免因为重放顺序导致约束冲突。DBOPTIONS SUPPRESSTRIGGERS让重放过程中不触发目标表上的触发器,防止业务触发器在同步链路上二次写数据,这一点如果漏配,很容易造成目标端数据翻倍。GROUPTRANSOPS 1000把 1000 个源事务合并成一个目标事务提交,是提升重放吞吐最直接的手段。
参数说明:REPERROR (DEFAULT, ABEND)表示遇到任何错误都终止进程,不做跳过。生产环境里也有人配成DISCARD,把错误行丢掉继续跑,但那等于让数据悄悄不一致,除非明确知道某些行可以放弃,否则不建议。ALLOWNOOPUPDATES处理源端更新了非关键列但目标端没有对应列的情况,避免报错。
GGSCI (test2) 18> add replicat repgs1, exttrail ./dirdat/gs, checkpointtable goldengate.ggschkpt REPLICAT added.注意这里先不要start,等初始化数据做完再按 SCN 启动,否则会跟导入的数据打架。
4.4 DDL 同步的四个脚本与表级 trandata
如果需要同步 DDL(建表、加列、索引变更),源端要额外跑几个脚本,这一步在只做 DML 同步时可以省略,但跨平台迁移阶段基本都会遇到。
-- 源端以 sysdba 执行 SQL> grant execute on utl_file to goldengate; SQL> @/u01/app/ogg/marker_setup SQL> @/u01/app/ogg/ddl_setup SQL> @/u01/app/ogg/role_setup SQL> GRANT GGS_GGSUSER_ROLE TO goldengate; SQL> @/u01/app/ogg/ddl_enable -- 可选:把 DDL 相关包 pin 到共享池,减少重装带来的性能抖动 SQL> @?/rdbms/admin/dbmspool.sql SQL> @/u01/app/ogg/ddl_pin goldengate逻辑说明:marker_setup建 DDL 同步需要的 marker 表,ddl_setup装 DDL 触发器,role_setup创建 OGG 专用角色,ddl_enable打开开关。四个脚本顺序不能乱,中间任何一个失败,后面的都会连不上。ddl_pin是可选项,把 OGG 用到的包固定在共享池,避免被换出后重新编译导致的短暂卡顿。
参数说明:ddl_pin的参数是 OGG 管理员 schema 名,必须跟 GLOBALS 里的GGSCHEMA一致。执行完这些脚本后,前面 Extract 参数里的DDL INCLUDE MAPPED才有意义,否则 DDL 语句会被静默忽略。
4.5 初始化数据:SCN 对齐的两种做法
存量数据不能靠 OGG 慢慢追,必须单独导一次。核心是让导出和 Extract 的起点对齐在同一个 SCN 上,顺序是先起 Extract,拿到当前 SCN,再按这个 SCN 导出。
-- 1. 记录当前 SCN SQL> select to_char(current_scn) from v$database; CURRENT_SCN ----------- 1085057 -- 2. 按该 SCN 导出源表 $ expdp test/test TABLES=test.t1 DUMPFILE=t1.dmp flashback_scn=1085057# 3. dump 文件拷到目标端后导入 $ impdp test/test dumpfile=t1.dmp # 4. 目标端按 SCN 启动 Replicat,只重放该 SCN 之后的变更 GGSCI (test2) 19> start replicat repgs1, aftercsn 1085057逻辑说明:flashback_scn保证导出的是那个时间点的一致性快照,aftercsn保证 Replicat 从同一个点之后开始重放,两边正好接上。如果先导数据再起 Extract,中间这段时间的变更就丢了;如果 Extract 起得太早、SCN 取得太晚,又会重复应用。我一般把select current_scn和start extract放在同一个脚本里连着执行,减少人为误差。
第二种做法是用sourceistable直接抽取,适合表不多、不想走 expdp 的场景:
GGSCI (test1) 20> add extract init_t1, sourceistable GGSCI (test1) 21> 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'; GGSCI (test1) 22> start extract init_t1目标端配一个 specialrun 的 Replicat 接收:
GGSCI (test2) 23> add replicat ri1, specialrun GGSCI (test2) 24> edit params ri1 REPLICAT ri1 SETENV (ORACLE_HOME = "/u01/app/oracle/product/11.2.0/db_1") SETENV (ORACLE_SID = "test2") USERID goldengate, PASSWORD goldengate EXTFILE ./dirdat/i1 MAP test.t1, TARGET test.t1;然后手工执行一次./replicat paramfile dirprm/ri1.prm完成初始化装载。注意 specialrun 不写 checkpoint,跑完就结束,不能用来做持续同步。
4.6 三种 DML 验证
初始化完成后,按插入、删除、清表三种操作各验一遍,覆盖最常见的三类变更:
-- 源端插入 SQL> insert into t1 (object_id) values (87366); SQL> commit; -- 目标端确认 SQL> select max(object_id) from test.t1; MAX(OBJECT_ID) -------------- 87366 -- 源端删除 SQL> delete from t1 where object_id = 87366; SQL> commit; -- 目标端确认回退 SQL> select max(object_id) from test.t1; MAX(OBJECT_ID) -------------- 87365 -- 源端清表 SQL> truncate table t1; -- 目标端确认 SQL> select count(*) from test.t1; COUNT(*) ---------- 0逻辑说明:插入验证的是 Extract 能抓到新行、Replicat 能正确构造 INSERT;删除验证的是主键定位是否准确,如果 trandata 没加对,删除可能变成全表扫描匹配或者直接报错;truncate 验证的是GETTRUNCATES是否在两端都生效,这一项经常被漏掉,表现是源端清空了、目标端还有几万行。
参数说明:如果 truncate 没同步过去,先查 Extract 参数里有没有GETTRUNCATES,再查 Replicat 参数,两处都要有。另外ALLOWNOOPUPDATES只影响更新,对 truncate 无效。
5. 避坑排查:跨平台链路里最容易翻车的五处
这条链路我在不同环境里配过几次,参数大差不差,但每次翻车的地方都很相似。下面五条按现象、原因、解决写,都是实际遇到过的。
5.1 进程类:MGR 正常但 Extract 起不来
现象:start mgr成功,info mgr显示 running,但start extgsxf后状态立刻变成 ABENDED,view report extgsxf里只有一行ERROR OGG-01032 There is a problem in the Oracle database.。
原因:九成是enable_goldengate_replication没开,或者开了但只在 memory 范围生效,实例重启后又回去了;剩下的一成是 OGG 账号缺dbms_goldengate_auth授权。
解决:show parameter enable_goldengate_replication确认是 TRUE,不是的话重新alter system set ... scope=both。再查select * from dba_sys_privs where grantee='GOLDENGATE',看有没有ALTER ANY TABLE、SELECT ANY TRANSACTION这类关键权限,缺了就重新跑一遍授权包,然后重启 MGR 和 Extract。
5.2 数据类:目标端有行但字段值是错的
现象:同步过去了,行数对得上,但中文名称字段是问号或者乱码,时间字段普遍差几个小时。
原因:字符集和时区。Windows 源库常见ZHS16GBK,Linux 目标库是AL32UTF8,如果 Extract 的NLS_LANG写成AMERICAN_AMERICA.AL32UTF8,读 GBK 数据时就会按 UTF-8 解析,直接乱码。
解决:Extract 里的NLS_LANG必须写成源库的实际字符集,比如AMERICAN_AMERICA.ZHS16GBK,Replicat 端写目标库字符集。时区问题查两端的DBTIMEZONE,不一致时在 Replicat 加SETENV (ORA_SDTZ="+08:00")显式指定会话时区。
5.3 配置类:Replicat 报 ORA-01403 找不到行
现象:Replicat 频繁ABENDED,报告里全是ORA-01403: no data found,对应的表明明有数据。
原因:update 或 delete 在目标端找不到匹配行。要么初始化数据的 SCN 对不上,导致某段变更丢失;要么SETENV (ORACLE_SID)写错了库,进程连到了别的实例。
解决:先info replicat repgs1, detail看它当前停在哪个 SCN,跟初始化时记录的 SCN 对比。如果 SCN 落后于实际导入点,就得重新初始化。ORACLE_SID这个坑特别隐蔽,参数文件是从源端拷过来改的,很容易忘改,我见过目标端参数里 SID 还写着源库实例名的,进程能起来,但写进的是完全不相干的库。
5.4 性能类:lag 越来越大,DataPump 是瓶颈
现象:info all里 Extract 的 lag 一直是个位数,DataPump 的 lag 从几十秒涨到几十分钟,目标端 Replicat 反而很闲。
原因:跨平台投递的网络吞吐不够,或者 trail 文件太小导致切换频繁。原文里megabytes 1024在变更量大的库上几小时就写满一个,切换时会有短暂停顿。
解决:先把add rmttrail的 megabytes 调到 2048 以上,减少文件切换;再检查网络,Windows 到 Linux 这段如果走了跨机房链路,RTT 高会显著拉低吞吐。DataPump 参数里的TCPFLUSHBYTES可以适当调大,默认 30KB 在高延迟链路上效率不高。
5.5 运维类:磁盘被 trail 文件撑爆
现象:运行一周后/u01使用率 100%,OGG 各进程还在跑,但新文件写不进去,链路静默中断。
原因:PURGEOLDEXTRACTS没配,或者配了但USECHECKPOINTS找不到 checkpoint 表,清理逻辑判定为不安全,直接跳过不删。
解决:MGR 参数里必须有PURGEOLDEXTRACTS ./dirdat/*, USECHECKPOINTS, MINKEEPHOURS 12,且 checkpoint 表必须存在并且能被读写。清理是按文件粒度的,最小保留单位是小时,一天内大量小文件的话清理速度跟不上产生速度,这种情况只能调大 trail 文件大小减少文件数。
6. 把链路看住:从 ggserr.log 到 lag 的三个固定动作
链路配完只是开始,能不能稳,取决于你多久看一次状态。我现在的习惯是每天早中晚各跑一遍固定动作,全部在 GGSCI 里完成,五分钟内能确认整条链路是否健康。
第一个动作看进程状态,重点不是 RUNNING,而是 lag 和 since:
GGSCI (test1) 1> info all Program Status Group Lag at Chkpt Time Since Chkpt MANAGER RUNNING EXTRACT RUNNING EXTGSXF 00:00:00 00:00:03 EXTRACT RUNNING DPGSKF 00:00:02 00:00:01Lag at Chkpt是检查点时间差,Time Since Chkpt是多久没更新检查点。如果后者持续增长到几分钟以上,即使状态是 RUNNING,也说明进程卡住了,通常是长事务或者网络抖动。这两个指标比单纯看状态可靠得多。
第二个动作翻日志。所有进程的异常都会写进 OGG 根目录下的ggserr.log,按时间倒序看最近的变化:
# 抓最近 200 行里的错误和警告 tail -n 200 /u01/app/ogg/ggserr.log | grep -Ei 'ERROR|WARNING|ABEND' # 单独看某个进程的详细报告 GGSCI (test1) 2> view report extgsxf报告里我最关注三块:Runtime Statistics里的每秒处理量,Long Running Transactions里有没有卡住的事务,以及Discarded Records是不是在增长。丢弃记录一旦出现,说明有行被跳过,必须马上查dirrpt下的 discard 文件。
第三个动作是定期做一次小批量数据比对。抽样比对源端和目标端的行数、最大主键、金额汇总,用一条 SQL 就能完成:
-- 在源端和目标端各执行一次,对比结果 select count(*) as cnt, max(object_id) as max_id, sum(object_id) as sum_id from test.t1;三个值都对上,基本可以确认链路没有静默丢数据。有次一个 update 因为目标端缺列被ALLOWNOOPUPDATES静默跳过,就是靠这个比对发现的,表面一切正常,实际已经偏了两天。
这套动作看起来笨,但比出事之后再回头翻日志快得多。从那以后我每次交付 OGG 链路,都会把这三个动作写进运维手册,并且强制要求上线首周每天执行一遍,把ggserr.log的轮转和 trail 目录的磁盘水位也一起纳入监控。链路这东西,平时不吵不闹,一坏就是数据层面的问题,后悔药是买不到的。希望帮到你。
本文还有配套的精品资源,点击获取