源端環境: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同步,又碰到源端經常變更修改字段的場景,對於運維人員來說是真的坑..