环境介绍:
源端:sybase数据库,服务器字符集iso_1,数据字符集cp936;
目标端:Oracle11g,字符集AL32UTF8。
replicat进程错误:
ERROR OGG-03517 Conversion from character set zhs16gbk of source column CYXM to character set UTF-8 of target column CYXM failed because the source column contains a character that is not available in the target character set.
解决心路历程:
一开始遇到这个问题,懵了,这是什么鬼,CYXM这个字段的字符转换错误?不对啊,logdump看了一下数据,再去源库看数据,没什么错呀。goldengate发什么疯,行吧,那我就根据前人的经验,使用SOURCECHARSET PASSTHRU这个参数。一重启,行啊,够给力的,进程不报错误了,数据库数据乱码了~呵呵哒。去看了官方介绍,原来SOURCECHARSET PASSTHRU这个参数是将我声明的源端字符集参数(ZHS16GBK)去掉,直接就将源端服务器字符集(ISO-8859-1)的数据插入进来,怪不得会乱码。看样子这个参数不能用。找了度娘好多次(目前还不会用Google),最后总结出现这个问题的原因可能是:
1. sybase的cp936字符集和oracle的zhs16gbk字符集是超集和子集的关系;
2. zhs16gbk 和 utf-8 字符转换存在编码问题。
故此,针对字符转换的问题,我是暂时没有解决方案了。但是突然想到,能不能跳过这个字符转换的错误呢?跑到Goldengate交流群上提问:
请问各位,Goldengate的replicat进程设置了出现错误记录到discart文件中,但是,这次出现了一个OGG-03517的错误,它直接就Abend了,错误报告是这条记录的一个字段字符集转换错误,我检查了一下,应该是中文字符集超集与子集的原因
但是,目前Oracle的字符集对中文的支持就只能这样了,所以我想让它出现类似错误时,不Abend,先记录discard文件
可以实现吗?
随风() 11:30:24
可以
广州-tan() 11:30:34
请问怎么设置?
PONG() 11:30:38
用这个参数应该可以
随风() 11:33:45
reperror(-03517,discard)
广州-tan() 11:35:46
@随风 可以写多个reperror参数吗
随风() 11:36:06
可以啊
广州-tan() 11:36:21
reperror(OGG-03517,discard)
reperror(Default,discard)
这样写?
随风() 11:36:23
两个错误就写两个就行
随风() 11:36:59
reperror(-03517,discard)
就这个写法
广州-tan() 11:37:42
那两个错误,是写两个reperror,还是写一个reperror
随风() 11:37:53
两个
写上不同错误号就行
广州-tan() 11:38:16
恩,多谢 @随风 @PONG
然后我就尝试使用REPERROR这个参数,想通过discard文件去捕获这个错误,不至于导致REPLICATE进程ABEND了,REPERROR的使用方式如下:
REPERROR { ( {DEFAULT | DEFAULT2 | SQL_error | user_defined_error}, {ABEND | DISCARD | EXCEPTION | IGNORE | RETRYOP [MAXRETRIES n] | TRANSABORT [, MAXRETRIES] [, DELAYSECS n | DELAYCSECS n] | TRANSDISCARD | TRANSEXCEPTION } ) | RESET }
将prm文件加入REPERROR参数后,我兴高采烈的start replicat进程,呵呵哒,还是abend。然后又去上了度娘,发现,REPERROR是可以捕获错误,但是OGG的错误,是没法捕获的啊~~~~。然后我又是一顿搜啊,最后在oracle的官方文档找到:
REPLACEBADCHARValid For
Extract and Replicat
Description
Use the REPLACEBADCHAR parameter to control the response of the process when a valid code point does not exist for either the source or target character set when mapping character-type columns. By default, the check for invalid code points is only performed when the source and target databases have different character sets, and the default response is to abend. You can use the FORCECHECK option to force the process to check for invalid code points when the source and target databases have the same character set. REPLACEBADCHAR applies globally.
Default
ABORT
Syntax
REPLACEBADCHAR {ABORT | SKIP | ESCAPE | SUBSTITUTE string | NULL | SPACE} [FORCECHECK] [NOWARNING]
MY GOD,我好像看到了救星,行了,就用你了。
我在prm文件中加入:
REPLACEBADCHAR SKIP NOWARING
目的:当出现某些字段的字符转换错误时,跳过此条记录,并不发出WARING信息。
注意:虽然官方解释道:如果使用skip选项,可能会导致数据不一致。但是吧,我这边使用该参数后,进程不报错了,数据也一致。我也在奇怪为什么会这个样子。不过现在进程至少不会因为这种字符转换的问题abend了,全部表的数据也能实时同步了。但是以后还是需要注意字符转换错误的那个表,看看数据是否一致,如果一致,那就不用鸟了。如果不一致,那只能再次排查,寻求解决方案了。
by the way,至于我为什么使用NOWARING选项,我喜欢,我高兴!
直接解决方案(不想看我一大堆废话的人儿):
REPLACEBADCHAR SKIP NOWARING
: