案例:OGG目标端进程ABENDED处理

源端环境:RHEL 6.5 + Oracle 11.2.0.4 RAC + OGG 19.1.0.0.4
目标端环境:RHEL 7.6 + Oracle 19.3 + OGG 19.1.0.0.4
故障现象:源端表结构某字段数据类型长度增加,并插入对应数据,目标端因还是之前的数据类型长度,导致应用进程无法更新对应数据进而导致ABENDED,一般来说,只需目标端依据源端修改为一致的字段长度即可,但这里发现依然会ABENDED,且报错信息不变。

先贴出最终解决方案(可作为后续解决同类问题的参考):

1.首先对比源端和目标端表结构

说明:示例均以JINGYU用户下的T1表为例说明:
注意不要只用desc去对比,同时要结合使用dbms_metadata.get_ddl去对比,避免遗漏约束类信息。
比如查看T1表的结构:

SQL>
desc JINGYU.T1
select dbms_metadata.get_ddl('TABLE','T1','JINGYU') from dual;

2.根据差异在目标端修改表结构保持和源端一致

比如修改T1表的TABLE_TYPE类型为VARCHAR2(30):

SQL>
alter table t1 modify TABLE_TYPE VARCHAR2(30);

此时当启动目标端应用进程,若观察可以稳定运行,则解决问题;若还是会自动ABENDED,且报错依然是表字段类型不匹配,则需要进行后面的步骤。

3.源端使用defgen生成表定义(只对曾出现问题的表进行),并传输到目标端

注意:这里曾出现问题的表是指要包含历史出现该问题的所有表,否则本次出问题的表修复了,历史表又很可能会出现同类问题。

配置参数defgen:

GGSCI> edit param defgen
defsfile dirdef/t1.def, purge
useridalias user
table JINGYU.T1;

在ogg安装目录下执行defgen生成表结构:

[oracle@jystdrac1 ogg19]$ ./defgen paramfile dirprm/defgen.prm

将生成的dirdef/t1.def文件传输到目标端对应目录dirdef下:

[oracle@jystdrac1 ogg19]$ scp dirdef/t1.def 192.168.1.19:/data/ggs/dirdef/

4.目标端编辑应用进程,添加如下内容,再次尝试启动进程

需注意:如果之前有assumetargetdefs参数,需将其注释掉,否则会报错参数冲突。

GGSCI> edit param repdef
--assumetargetdefs
SOURCEDEFS ./dirdef/t1.def OVERRIDE

此时再启动目标端应用进程,观察可以稳定运行,解决问题。

下面依据实际生产配置在测试环境重现此问题:
首先在OGG源端数据库中JINGYU用户下创建3张测试表T1,T2,T3。最终要求OGG目标端中IT用户下同步这三张表。

1.配置OGG源端抽取、投递进程

配置OGG源端抽取进程EXTDEF:

--抽取extract
GGSCI (lbryqdb02) 2> edit param EXTDEF

EXTRACT EXTDEF
SETENV (ORACLE_HOME="/opt/app/oracle/product/11.2.0/dbhome_1")
setenv (NLS_LANG="AMERICAN_AMERICA.AL32UTF8")
setenv (ORACLE_SID="crmdb1")
useridalias user
GETTRUNCATES
REPORTCOUNT EVERY 1 MINUTES, RATE
DISCARDFILE ./dirrpt/EXTDEF.dsc,APPEND,MEGABYTES 1000
WARNLONGTRANS 2h,CHECKINTERVAL 10m
EXTTRAIL ./dirdat/ee
TRANLOGOPTIONS DBLOGREADER
TRANLOGOPTIONS EXCLUDEUSER ogg
DBOPTIONS ALLOWUNUSEDCOLUMN
DYNAMICRESOLUTION
CACHEMGR CACHESIZE 4GB
FETCHOPTIONS FETCHPKUPDATECOLS
--ext tables
TABLE JINGYU.T1;
TABLE JINGYU.T2;
TABLE JINGYU.T3;

--添加抽取进程:
add extract EXTDEF, tranlog, THREADS 2, begin now
add exttrail ./dirdat/ee, extract EXTDEF

配置OGG源端投递进程DPDEF:

--投递datapump
GGSCI (lbryqdb02) 4> edit param DPDEF

EXTRACT DPDEF
RMTHOST 192.168.1.19, MGRPORT 7809, compress
PASSTHRU
RMTTRAIL ./dirdat/re
DYNAMICRESOLUTION
--ext tables
TABLE JINGYU.T1;
TABLE JINGYU.T2;
TABLE JINGYU.T3;

--添加投递进程:
add extract DPDEF, exttrailsource ./dirdat/ee
add rmttrail ./dirdat/re, extract DPDEF

2.开启OGG源端数据库、表附加日志

SQL> 
--查看数据库附加日志开启状态:
select SUPPLEMENTAL_LOG_DATA_MIN, SUPPLEMENTAL_LOG_DATA_PK, SUPPLEMENTAL_LOG_DATA_UI from v$database;

--数据库级别开启最小附加日志:
alter database add supplemental log data;

--表级别开启详细附加日志:
GGSCI>
dblogin useridalias user
add trandata jingyu.t1
add trandata jingyu.t2
add trandata jingyu.t3

到这里就可以先启动OGG源端的抽取和投递进程了:

GGSCI>
start EXTDEF
start DPDEF

然后将需要同步的表在目标端初始化(其实这里测试表都没有数据,直接目标端创建也可)

[oracle@jystdrac1 ~]$ exp jingyu/jingyu file=oggs.dump tables=T1,T2,T3
[oracle@jystdrac1 ~]$ scp oggs.dump 192.168.1.19:/home/oracle/
[oracle@db19 ~]$ imp it/it@orclpdb1 file=oggs.dump full=y

3.配置OGG目标端应用进程

配置OGG目标端应用进程REPDEF:

--OGG目标端:
应用replicate
GGSCI (lOGGdb01) 2> edit param REPDEF

REPLICAT REPDEF
SETENV (ORACLE_HOME="/opt/oracle/product/19c/dbhome_1")
setenv (NLS_LANG="AMERICAN_AMERICA.AL32UTF8")
setenv (ORACLE_SID="ORCLCDB")
--useridalias oggpdb
USERIDALIAS ogg domain pdbs
--SQLEXEC "ALTER SESSION SET CONSTRAINTS=DEFERRED"
REPORT AT 01:59
REPORTCOUNT EVERY 30 MINUTES, RATE
REPERROR DEFAULT, ABEND
--numfiles 5000
--HANDLECOLLISIONS
assumetargetdefs
DISCARDFILE ./dirrpt/REPDEF.dsc, APPEND, MEGABYTES 1000
GETTRUNCATES
ALLOWNOOPUPDATES
--table20200422
MAP JINGYU.T1, TARGET IT.T1;
MAP JINGYU.T2, TARGET IT.T2;
MAP JINGYU.T3, TARGET IT.T3;

--添加应用进程:
add replicat REPDEF, exttrail ./dirdat/re, nodbcheckpoint

启动应用进程:

GGSCI>
start REPDEF

4.测试过程

4.1 源端OGG库插入数据,目标端可以正常同步

insert into t1 values ('1','1A');
insert into t2 values ('1','2A');
insert into t3 values ('1','3A');
commit;
insert into t1 values ('2','1B');
insert into t2 values ('2','2B');
insert into t3 values ('2','3B');
commit;

select * from t1;
select * from t2;
select * from t3;

4.2 源端表T1字段TABLE_TYPE数据类型

--修改t1字段类型
--VARCHAR2(20) -> VARCHAR2(30)
jingyu@CRMDB> alter table t1 modify TABLE_TYPE VARCHAR2(30);
--源端插入大于之前VARCHAR2(20)的数据
insert into t1 values ('3','1C1C1C1C1C1C1C1C1C1C1C1C1C1C');
commit;

--目标端OGG终止ABENDED:
GGSCI (db19) 19> info all

Program     Status      Group       Lag at Chkpt  Time Since Chkpt

MANAGER     RUNNING                                           
REPLICAT    RUNNING     REPAUD1A    00:00:00      00:00:00    
REPLICAT    ABENDED     REPDEF      00:00:00      00:00:11  

--错误信息很明确,就是插入了长度为28的数据,但是最大允许长度是20:
2020-07-17T09:52:47.041+0800  ERROR   OGG-01163  Oracle GoldenGate Delivery for Oracle, repdef.prm:  Bad column length (28) specified for column TABLE_TYPE in table JINGYU.T1, maximum allowable length is 20.
2020-07-17T09:52:47.042+0800  INFO    OGG-02333  Oracle GoldenGate Delivery for Oracle, repdef.prm:  Reading /data/ggs/dirdat/re000000000, current RBA 4,164, 9 records, m_file_seqno = 0, m_file_rba = 4,321.
2020-07-17T09:52:47.044+0800  ERROR   OGG-01668  Oracle GoldenGate Delivery for Oracle, repdef.prm:  PROCESS ABENDING.

4.3 目标端表T1手工修改字段TABLE_TYPE数据类型

--目标端表T1手工修改字段TABLE_TYPE数据类型为VARCHAR2(30)
SQL> alter table t1 modify TABLE_TYPE VARCHAR2(30);
--尝试启动目标端OGG应用进程
GGSCI (db19) 20> start repdef

Sending START request to MANAGER ...
REPLICAT REPDEF starting
--依然报错:
2020-07-17T09:53:56.668+0800  ERROR   OGG-01163  Oracle GoldenGate Delivery for Oracle, repdef.prm:  Bad column length (28) specified for column TABLE_TYPE in table JINGYU.T1, maximum allowable length is 20.
2020-07-17T09:53:56.668+0800  INFO    OGG-02333  Oracle GoldenGate Delivery for Oracle, repdef.prm:  Reading /data/ggs/dirdat/re000000000, current RBA 4,164, 0 records, m_file_seqno = 0, m_file_rba = 4,321.
2020-07-17T09:53:56.668+0800  ERROR   OGG-01668  Oracle GoldenGate Delivery for Oracle, repdef.prm:  PROCESS ABENDING.

4.4 源端使用defgen生成表定义(只对出现问题的表进行),并传输到目标端

配置参数defgen:

GGSCI> edit param defgen
defsfile dirdef/t1.def, purge
useridalias user
table JINGYU.T1;

在ogg安装目录下执行defgen生成表结构:

[oracle@jystdrac1 ogg19]$ ./defgen paramfile dirprm/defgen.prm

将生成的dirdef/t1.def文件传输到目标端对应目录dirdef下:

[oracle@jystdrac1 ogg19]$ scp dirdef/t1.def 192.168.1.19:/data/ggs/dirdef/

4.5 目标端编辑应用进程,添加如下内容,再次尝试启动进程

GGSCI> edit param repdef
SOURCEDEFS ./dirdef/t1.def OVERRIDE
--报错参数冲突
2020-07-17T10:03:03.731+0800  ERROR   OGG-10107  Oracle GoldenGate Delivery for Oracle, repdef.prm:  (repdef.prm) line 21: Parsing error, parameter [sourcedefs] conflicts with parameter [assumetargetdefs].
2020-07-17T10:03:03.731+0800  ERROR   OGG-10107  Oracle GoldenGate Delivery for Oracle, repdef.prm:  (repdef.prm) line 21: Parsing error, parameter [assumetargetdefs] conflicts with parameter [sourcedefs].
2020-07-17T10:03:03.731+0800  ERROR   OGG-01668  Oracle GoldenGate Delivery for Oracle, repdef.prm:  PROCESS ABENDING.
--注释/删除掉提示冲突的参数
--assumetargetdefs

此时启动进程成功,稳定运行,去观察目标端表T1,已经同步正常:

SQL> select * from t1;

TABLE_NAME                     TABLE_TYPE
------------------------------ ------------------------------
3                              1C1C1C1C1C1C1C1C1C1C1C1C1C1C
1                              1A
2                              1B

再测试OGG源端更新,观察目标端同步其他表数据均正常:

insert into t1 values ('4','1D');
insert into t2 values ('4','2D');
insert into t3 values ('4','3D');
commit;

select * from t1;
select * from t2;
select * from t3;

--目标端查看确认同步正常。

4.6 各种不确认的猜想场景测试

场景1:如果把这个参数现在去掉是否可以呢?

--注释掉`SOURCEDEFS ./dirdef/t1.def OVERRIDE`,然后重启 repdef进程,再次插入就会报错
insert into t1 values ('6','1C1C1C1C1C1C1C1C1C1C1C1C1C1C');
commit;
--发现又一次报错:
2020-07-17T10:17:43.641+0800  ERROR   OGG-01163  Oracle GoldenGate Delivery for Oracle, repdef.prm:  Bad column length (28) specified for column TABLE_TYPE in table JINGYU.T1, maximum allowable length is 20.
2020-07-17T10:17:43.641+0800  INFO    OGG-02333  Oracle GoldenGate Delivery for Oracle, repdef.prm:  Reading /data/ggs/dirdat/re000000000, current RBA 4,807, 0 records, m_file_seqno = 0, m_file_rba = 4,964.
2020-07-17T10:17:43.641+0800  ERROR   OGG-01668  Oracle GoldenGate Delivery for Oracle, repdef.prm:  PROCESS ABENDING.

说明这个参数不能去掉,也就是说dirdef下的文件也不能删除。

场景2:假设表T2的表结构又变化了,会怎样?

alter table t2 modify TABLE_TYPE VARCHAR2(30);

insert into t2 values ('7','1C1C1C1C1C1C1C1C1C1C1C1C1C1C');
commit;
--发现T2报错:
2020-07-17T10:24:26.183+0800  ERROR   OGG-01163  Oracle GoldenGate Delivery for Oracle, repdef.prm:  Bad column length (28) specified for column TABLE_TYPE in table JINGYU.T2, maximum allowable length is 20.
2020-07-17T10:24:26.184+0800  INFO    OGG-02333  Oracle GoldenGate Delivery for Oracle, repdef.prm:  Reading /data/ggs/dirdat/re000000000, current RBA 4,964, 1 records, m_file_seqno = 0, m_file_rba = 5,120.
2020-07-17T10:24:26.184+0800  ERROR   OGG-01668  Oracle GoldenGate Delivery for Oracle, repdef.prm:  PROCESS ABENDING.

结合场景1,若此时再按照单表的方式进行操作,实际会出现死循环,参见后面的场景4。

场景3:目标端OGG如果没有手工改字段类型,直接defgen修改定义会怎样?

可以继续场景2的测试,不修改T2表字段类型,直接defgen修改定义:

TABLE_NAME                     TABLE_TYPE
------------------------------ --------------------
4                              2D
7                              1C1C1C1C1C1C1C1C1C1C
1                              2A
2                              2B

纳尼?可以同步数据?但这个数据居然会被截断?!

场景4:场景2延续,修复时只修复T2,会怎样?
其实大家肯定能推理出来了,如果这样的话,再插入T1表超长的字段就又会报错:

insert into t1 values ('8','1C1C1C1C1C1C1C1C1C1C1C1C1C1C');
commit;
--T1又会报错:
2020-07-17T10:29:38.772+0800  ERROR   OGG-01163  Oracle GoldenGate Delivery for Oracle, repdef.prm:  Bad column length (28) specified for column TABLE_TYPE in table JINGYU.T1, maximum allowable length is 20.
2020-07-17T10:29:38.775+0800  INFO    OGG-02333  Oracle GoldenGate Delivery for Oracle, repdef.prm:  Reading /data/ggs/dirdat/re000000000, current RBA 5,120, 1 records, m_file_seqno = 0, m_file_rba = 5,277.
2020-07-17T10:29:38.776+0800  ERROR   OGG-01668  Oracle GoldenGate Delivery for Oracle, repdef.prm:  PROCESS ABENDING.

需要T1,T2都要修改定义才可以。那为了避免这么麻烦,我们遇到这样的场景,要不就所有表都生成下定义?
不行!如果所有表都改的话,如果目标端有其他表字段有问题,数据都会插入进去且看不到报错(实际表现就是出现数据被截断存储的现象,参见场景3)。
好吧,看来只能发现一次问题修复一次。或者已知本次就是修改的表结构较多,一次性对比所有表结构,给所有表重新生成定义。
最后感叹下,OGG的使用必须要配合客户的规范化管理,否则当没有配置ddl同步,又碰到源端经常变更修改字段的场景,对于运维人员来说是真的坑..

This entry was posted in Oracle故障处理 and tagged , . Bookmark the permalink.