源端环境: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.首先对比源端和目标端表结构
- 2.根据差异在目标端修改表结构保持和源端一致
- 3.源端使用defgen生成表定义(只对曾出现问题的表进行),并传输到目标端
- 4.目标端编辑应用进程,添加如下内容,再次尝试启动进程
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同步,又碰到源端经常变更修改字段的场景,对于运维人员来说是真的坑..