Oracle GoldenGate Replicat Abend:Key Column Missing 根因分析与修复

一、故障现象

某生产环境 Oracle GoldenGate 19c 的 Replicat 进程 REP_LIB 突然 Abend,Report 日志抛出核心错误:

复制代码
ERROR   OGG-01296  Error mapping from [SRC_SCHEMA].SRTCONTAINER to [TGT_SCHEMA].SRTCONTAINER.
ERROR   OGG-01668  PROCESS ABENDING.

进程停止前最后一条有效警告:

复制代码
WARNING OGG-01431  Aborted grouped transaction on [TGT_SCHEMA].SRTCONTAINER, Mapping error.
WARNING OGG-01151  Error mapping from [SRC_SCHEMA].SRTCONTAINER to [TGT_SCHEMA].SRTCONTAINER.

同时,discard 文件记录了决定性线索:

复制代码
Key column DATAID (0) is missing from update on table [TGT_SCHEMA].SRTCONTAINER
Missing 1 key columns in update for table [TGT_SCHEMA].SRTCONTAINER.

二、环境信息

组件 版本/信息
OGG 版本 19.1.0.0.4
操作系统 Linux x86_64
源端数据库 Oracle 19c,字符集 ZHS16GBK
目标端数据库 Oracle 19c,字符集 ZHS16GBK
Replicat 类型 Classic Replicat

三、排查过程

3.1 第一步:查看 Discard 文件

Discard 文件是第一现场。与常见的 ORA-00001(唯一冲突)或 ORA-12899(值太大)不同,这次 discard 没有任何 Oracle 错误号,而是直接指出:

Key column DATAID is missing from update

这说明 Replicat 在构建 UPDATE ... WHERE 语句时,发现定位行所需的键列 DATAID 在 trail 记录中不存在,导致无法定位目标行。

3.2 第二步:对比源端与目标端表结构

分别检查源端和目标端的 SRTCONTAINER 表:

结论:列名、列顺序、数据类型完全一致,但 NOT NULL 约束不同。

更关键的是索引差异

源端索引:

复制代码
TR_SRTCONTAINER_PK    SRTCONTAINERID    UNIQUE

目标端索引:

复制代码
PK_SRTCONTAINER       DATAID, SRTCONTAINERID    UNIQUE

发现:

  • 源端业务主键是单列 SRTCONTAINERID
  • 目标端主键是复合主键 (DATAID, SRTCONTAINERID)

3.3 第三步:检查 OGG 自动识别的 Key Columns

Replicat 启动日志明确显示:

复制代码
INFO    OGG-06510  Using the following key columns for target table [TGT_SCHEMA].SRTCONTAINER: DATAID, SRTCONTAINERID.

OGG 自动识别了目标端的复合主键,并将其作为该表的 Key Columns(用于在目标端定位行的列)。

3.4 第四步:检查源端补充日志

sql 复制代码
SELECT SUPPLEMENTAL_LOG_DATA_PK FROM V$DATABASE;
-- 结果:NO

源端数据库未开启主键补充日志

四、根因分析

4.1 OGG 的 Key Columns 识别机制

在 Classic Replicat 中,OGG 会按以下优先级自动确定目标表的 Key Columns:

  1. 目标端的主键(Primary Key)
  2. 目标端的唯一索引(Unique Index)
  3. 目标端所有 NOT NULL 列

本案例中,目标端存在复合主键 PK_SRTCONTAINER(DATAID, SRTCONTAINERID),因此 OGG 自动将 DATAIDSRTCONTAINERID 同时作为 Key Columns。

4.2 压缩更新与 Trail 记录内容

OGG Extract 默认使用**压缩更新(Compressed Updates)**模式。对于一条 UPDATE 语句,trail 中通常只包含:

  • 被修改的列(After Image)
  • Key Columns(用于在目标端定位行的列,取自源端的主键/唯一索引)

问题就出在这里:

主键/唯一键 对 OGG 的意义
源端 TR_SRTCONTAINER_PK(SRTCONTAINERID) Extract 认为 Key = SRTCONTAINERID,因此 trail 中只保证携带 SRTCONTAINERID
目标端 PK_SRTCONTAINER(DATAID, SRTCONTAINERID) Replicat 认为 Key = DATAID + SRTCONTAINERID,构建 SQL 时需要这两个值

当源端执行如下 UPDATE 时:

sql 复制代码
UPDATE SRTCONTAINER 
SET UPDATETIME = ..., UPDATER = ..., STATUS = ... 
WHERE SRTCONTAINERID = '...';
  • DATAID 既不是被修改的列也不是源端的主键/唯一索引列
  • 在压缩更新模式下,Extract 不会将 DATAID 写入 trail
  • Replicat 收到记录后,发现需要 DATAID 来构建 WHERE DATAID = ? AND SRTCONTAINERID = ?,但 trail 中没有 → 报错 Key column DATAID is missing

4.3 补充日志的角色

源端 SUPPLEMENTAL_LOG_DATA_PK = NO 意味着 Oracle redo 不会强制记录主键列的完整前像。虽然即使开启 PK 补充日志,由于 DATAID 并非源端主键的一部分 ,依然无法解决 DATAID 缺失的问题;但未开启补充日志确实是 OGG 部署的一个潜在风险点,它限制了 Extract 在更复杂场景下获取完整键值的能力。

4.4 根因总结图

复制代码
源端 UPDATE (只改 UPDATER/STATUS/UPDATETIME)
        │
        ▼
Extract 识别源端 Key = SRTCONTAINERID
        │
        ▼
Trail 记录包含:修改列 + SRTCONTAINERID
        │
        ▼
Replicat 识别目标端 Key = DATAID + SRTCONTAINERID
        │
        ▼
构建 UPDATE ... WHERE DATAID=? AND SRTCONTAINERID=?
        │
        ▼
Trail 中无 DATAID ────────► Key column DATAID is missing
                                    │
                                    ▼
                           OGG-01296 Mapping Error
                                    │
                                    ▼
                           OGG-01668 PROCESS ABENDING

一句话根因:目标端复合主键包含的 DATAID 列,在源端 UPDATE 产生的 trail 记录中缺失,导致 Replicat 无法构建完整的行定位条件。

五、解决方案

5.1 方案选择

由于源端业务上 SRTCONTAINERID 已能唯一标识一行(源端有唯一索引,且目标端验证无重复值),最简洁的方案是在 Replicat 参数中显式覆盖自动识别的 Key Columns ,强制只使用 SRTCONTAINERID 定位:

bash 复制代码
MAP [SRC_SCHEMA].SRTCONTAINER, TARGET [TGT_SCHEMA].SRTCONTAINER, KEYCOLS (SRTCONTAINERID);

注意: 该参数必须放在通配符 MAP [SRC_SCHEMA].*.* 之前,否则会被通配符抢先匹配。

5.2 为什么不选其他方案?

方案 说明 未选原因
修改目标表结构 去掉 DATAID 或改为单列主键 涉及业务系统改造,风险极高

5.3 参数修改示例

bash 复制代码
REPLICAT rep_lib
SETENV (ORACLE_HOME = "$ORACLE_HOME")
SETENV (ORACLE_SID = "[DB_NAME]")
SETENV (NLS_LANG = "AMERICAN_AMERICA.ZHS16GBK")
USERID [OGG_USER] password ***
ASSUMETARGETDEFS
DBOPTIONS DEFERREFCONST
DBOPTIONS SUPPRESSTRIGGERS
DISCARDFILE ./dirrpt/rep_lib.dsc, APPEND, MEGABYTES 1000
REPERROR (DEFAULT, ABEND)
DDL INCLUDE MAPPED, OBJTYPE 'TABLE' &
INCLUDE MAPPED OBJTYPE 'INDEX'
GROUPTRANSOPS 1000
-- 显式指定 Key Columns(必须放在通配符之前)
MAP [SRC_SCHEMA].SRTCONTAINER, TARGET [TGT_SCHEMA].SRTCONTAINER, KEYCOLS (SRTCONTAINERID);
-- 通配符映射
MAP [SRC_SCHEMA].*.*, TARGET [TGT_SCHEMA].*.*;
...

修改后重启:

bash 复制代码
GGSCI> stop rep_lib
GGSCI> start rep_lib

六、经验总结与最佳实践

6.1 源端与目标端主键不一致是常见陷阱

在异构同步或数仓场景中,目标端常会增加代理键、分区键或数据仓库键,形成与源端不同的主键结构。OGG 默认按目标端约束识别 Key Columns,一旦目标端主键列在源端 trail 中无法获取,就会触发本案例的故障。

建议: 在 OGG 投产前,梳理所有同步表的源端/目标端主键差异,对不一致的表提前配置 KEYCOLSFETCHCOLS

6.2 补充日志是 OGG 的基石

虽然本次故障的直接原因不是补充日志,但 SUPPLEMENTAL_LOG_DATA_PK = NO 是一个显著风险。建议源端开启:

sql 复制代码
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;

这能确保 Extract 在绝大多数场景下获取到完整的主键值。

6.3 Discard 文件是排障的第一现场

遇到 Mapping Error 时,不要只看 Report 日志的 OGG-01296一定要第一时间查看 discard 文件 。discard 中的 Key column XXX is missing 直接指明了缺失的列,能大幅缩短排障路径。

6.4 KEYCOLS 的适用边界

使用 KEYCOLS 强制指定定位列时,必须确保该列在业务上真正唯一。修改前应在目标端验证:

sql 复制代码
SELECT SRTCONTAINERID, COUNT(*) 
FROM [TGT_SCHEMA].SRTCONTAINER 
GROUP BY SRTCONTAINERID 
HAVING COUNT(*) > 1;

返回 no rows selected 方可安全使用。


关键词: Oracle GoldenGate, Replicat Abend, OGG-01296, Key Column Missing, COMPRESSUPDATES, Supplemental Log, KEYCOLS, Mapping Error

相关推荐
IvorySQL10 小时前
PostgreSQL 日报 | JOIN 与外键优化(8 月 9 日)
数据库·postgresql
ltl11 小时前
自治数据库十年回顾:Peloton、NoisePage、OtterTune 到云原生 auto-tuning
数据库
灯澜忆梦12 小时前
【MySQL10】进阶篇 | 索引_#2性能优化
数据库·sql·mysql·性能优化
C++ 老炮儿的技术栈14 小时前
从 Qt Designer 属性编辑器的层级可以看到继承链
c语言·数据库·c++·qt·sqlite·visual studio
MC皮蛋侠客14 小时前
Redis 系列(一):全景与最小闭环——从 `SET` 命令到内存数据结构
数据结构·数据库·redis
zt1985q16 小时前
本地部署开源网络书签与内容管理工具 Karakeep 并实现外部访问
运维·服务器·网络·数据库·网络协议·开源
IvorySQL16 小时前
PostgreSQL 日报| PostgreSQL 19 默认 WAL 压缩算法(8 月 8 日)
数据库·postgresql·区块链
油丶酸萝卜别吃17 小时前
MySQL B+ 树查询全过程详解
数据库·mysql
leisoo809717 小时前
股票数据本地化存储实战:JSON、数据库与列式存储的方案对比
jvm·数据库·json