关于gg的列名映射问题
源表结构:id,vl
目标表结构:
id,vl1
1)案例1:
配置文件如下:
extract extl
userid ggate@ggdb01,password ggate
rmthost 10.1.19.90, mgrport 7801
rmttrail /home/oracle/gg_trail/rl
dynamicresolution
ddl include objname cgb.* objtype 'table'
--DDL INCLUDE ALL OPTYPE CREATE OBJTYPE 'table'
--DDLERROR RESTARTSKIP 100000 SKIPTRIGGERERROR 100000
DDLOPTIONS ADDTRANDATA,REPORT
table cgb.*;
sequence cgb.*;
replicat repl
SETENV (ORACLE_HOME = "/u01/app/oracle/app/product/11.2.0/db")
SETENV (ORACLE_SID = "ggdb02")
userid ggate@ggdb02,password ggate
assumetargetdefs
SOURCEDEFS /home/oracle/gg_def/j1.def
reperror default,discard
discardfile /home/oracle/gg_log/repsz.dsc,append,megabytes 100
ddl include objname cgb.* objtype 'table'
--DDL INCLUDE ALL OPTYPE CREATE OBJTYPE 'table'
DDLERROR DEFAULT IGNORE
DDLOPTIONS REPORT
--MAP cgb.j1, TARGET cgb.j1,
--COLMAP (usedefaults,
--vl1 = vl);
map cgb.*, target cgb.*;
从上面可以看出配置文件是存在问题的,源表和目标表的第二个字段名称不一样,但配置文件确指定了assumetargetdefs选项。
在源端数据库插入一条记录:
insert into cgb.j1(id,vl) values(1,'a');
此时查看目标端的数据库记录:
select id,vl1 from cgb,j1 where id=1;
结果发现一条id=1,vl1=null的记录
2)案例2:
配置文件如下:
replicat repl
SETENV (ORACLE_HOME = "/u01/app/oracle/app/product/11.2.0/db")
SETENV (ORACLE_SID = "ggdb02")
userid ggate@ggdb02,password ggate
assumetargetdefs
--SOURCEDEFS /home/oracle/gg_def/j1.def
reperror default,discard
discardfile /home/oracle/gg_log/repsz.dsc,append,megabytes 100
ddl include objname cgb.* objtype 'table'
--DDL INCLUDE ALL OPTYPE CREATE OBJTYPE 'table'
DDLERROR DEFAULT IGNORE
DDLOPTIONS REPORT
--MAP cgb.j1, TARGET cgb.j1,
--COLMAP (usedefaults,
--vl1 = vl);
map cgb.*, target cgb.*;
和上一个案例不同的地方只是取消了SOURCEDEFS
在源端数据库插入一条记录:
insert into cgb.j1(id,vl) values(1,'a');
此时查看目标端的数据库记录:
select id,vl1 from cgb,j1 where id=1;
这次更加奇怪了,结果发现一条id=1,vl1=a的记录,也就是记录完全正确的同步过去了
问题:
为什么列名错误映射也能成功插入数据,比如insert into cgb.j1(id,vl1) values(1,'a')这条记录,按rep的配置(assumetargetdefs)目标端应该映射为insert into cgb.j1(id,vl1) values(1,'a')才对吧,这样在目标端执行应该会报错才对啊,为什么还能成功插入呢? Using default column mapping
If an explicit column mapping does not exist, either by using COLMATCH or COLMAP, Oracle GoldenGate maps source and target columns by default according to the following rules.
● Columns with the same name are mapped to each other if the data types are compatible.
● For databases that do not support case-sensitivity for object names, column names are changed to uppercase for name comparison. For databases that are configured for casesensitivity, Oracle GoldenGate considers the case when evaluating columns for default mapping.
● If a source column is found whose name and case exactly match those of the target column, the two are mapped. If no case match is found, then the map is created using the first eligible source column whose name matches that of the target column, regardless of case.
● Target columns that do not correspond to any source column take default values determined by the database.
file:///C:/Users/Administrator/AppData/Roaming/Tencent/Users/29719318/QQ/WinTemp/RichOle/~QS%60)TY)£%254~R)UUL%7BQ6A.jpg 谢谢,这个第一个案例可以说得通,但是第二个案例说不通哦... 这个很好解释的,如果你使用过logminer的话,你就能理解,对日志进行挖掘的时候,需要从数据库里去查询对象的名称。因为日志文件里只含有对象id而无名称。同样的道理,goldengate抽取出来的队列文件里是不包含字段名称的,只包含字段的id.如下所示:Logdump 28 >n
___________________________________________________________________
Hdr-Ind : E (x45) Partition : . (x04)
UndoFlag : . (x00) BeforeAfter: A (x41)
RecLength : 27 (x001b) IO Time : 2012/01/05 17:36:13.000.000
IOType : 5 (x05) OrigNode : 255 (xff)
TransInd : . (x02) FormatType : R (x52)
SyskeyLen : 0 (x00) Incomplete : . (x00)
AuditRBA : 5 AuditPos : 21343248
Continued : N (x00) RecCount : 1 (x01)
2012/01/05 17:36:13.000.000 Insert Len 27 RBA 1339
Name: MYTESTSRC.TEST3
After Image: Partition 4 G e
0000 0005 0000 0001 3600 0100 0e00 0000 0a30 352d | ........6........05-
31d4 c220 2d31 32 | 1.. -12
Column 0 (x0000), Len 5 (x0005)
0000 0001 36 | ....6
Column 1 (x0001), Len 14 (x000e)
0000 000a 3035 2d31 d4c2 202d 3132 | ....05-1.. -12
GGS tokens:
TokenID x52 'R' ORAROWID Info x00 Length 20
4141 414d 314d 4141 4541 4141 4147 3441 4144 0001 | AAAM1MAAEAAAAG4AAD..
TokenID x4c 'L' LOGCSN Info x00 Length 7
3132 3938 3633 30 | 1298630
TokenID x36 '6' TRANID Info x00 Length 8
382e 3434 2e36 3036 | 8.44.606
这个在源数据库里scn为1298630,事务号xid为8.44.606的insert操作:插入两个字段column 0 , column 1
当目标端复制进程进行复制时,现在的问题就是复制进程将这个操作再次转换为sql语句,它需要知道这个insert mytestsrc.test3这个表的字段名称。
有两种方式一种是从数据库里取,一种是从def定义文件里取取。
对应你的情况就是,当你不生成def文件(实际上同构环境下也不需要生成def文件),从目标端数据库里取。
所以它不管你的字段名称是什么,只根据队列文件里的column id去得到这个字段名称,就会根据字段名称生成insert语句,然后在目标库上执行这个sql语句。
当你用def文件时,goldengate就从你的def文件里得到字段名称:
def文件内容如下:
Definition for table MYTEST.TEST11
Record length: 74
Syskey: 0
Columns: 2
ID 64 50 0 0 0 1 0 50 50 50 0 0 0 0 1 0 1 2
NAME 64 12 56 0 0 1 0 12 12 0 0 0 0 0 1 0 1 0
End of definition
所以当ogg从目标库获取字段名称生成sql语句时,表结构发生变化时而没开启ddl时, 删除或增加字段导致字段id变化时,字段名称一样,两端id序号不一样时,字段插入顺序也会混乱,把源端c字段插入目标端d字段。
如果你测试过goldengate ALO模式下的复制,你就能深入理解这个过程了。你可以从源数据库拷贝归档到其他主机上,在其他主机上建立一个object id 数据库(这个数据库只包含源system,undo,temp表空间),让goldengate工作于alo模式去从归档抽取数据,当你的表结构不发生变更时,你甚至可以让抽取进程在启动时一次性加载完所有的表然后直接关闭数据库,抽取进程也是可以正常工作的。这里我先前有错误,这里是加载的表的名称。
file:///C:\Users\lavender010\AppData\Roaming\Tencent\Users\275897695\QQ\WinTemp\RichOle\XSWFG5E%L78)B0FAD6E0_ER.jpg
[ 本帖最后由 newway 于 2012-7-23 15:49 编辑 ]
回复 newway
你也在这个群? 好贴 授精回复 4# 的帖子
讲解的很精彩,也很到位! 好贴,谢谢
页:
[1]