goldengate同步无主键无唯一索引表的问题以及解决方案
一【环境描述】
1、goldengate版本
./ggsci -v
Oracle GoldenGate Command Interpreter for Oracle
Version 11.2.1.0.4_02 15864821 OGGCORE_11.2.1.0.5_PLATFORMS_121214.0600_FBO
Linux, x64, 64bit (optimized), Oracle 11g on Dec 14 2012 11:41:04
2、database版本
sqlplus -v
SQL*Plus: Release 11.2.0.3.0 Production
3、表结构
备注:表无任何索引和约束,sxiaoxu表示源表,txiaoxu表示目标表.
create table sxiaoxu
(
id int not null,
name varchar2(50),
age int not null,
sex char(1)
)
create table txiaoxu
(
id int not null,
name varchar2(50),
age int not null,
sex char(1)
)
4、测试场景
4.1 构建完全相同数据,更新全部数据以及随机更新数据,查看目标端更新情况
4.2构造keycols相同的整条记录不相同,更新全部数据以及随机更新数据,查看目标端更新情况
4.3当表结构发生变化时,验证同步存在问题
4.4当表结构存在大字段类型时,更新数据,查看目标端更新情况
二【测试过程针对构建完全相同以及keycols相同的记录不同】
备注--构建完全相同数据,更新全部数据以及随机更新数据,查看目标端更新情况
--准备工作完成包括配置抽取进程,应用进程以及数据库级别附加日志、表附加日志
1、验证表附加日志是所有列
info trandata XIAOXU.SXIAOXU
Logging of supplemental redo log data is enabled for table XIAOXU.SXIAOXU.
Columns supplementally logged for table XIAOXU.SXIAOXU: AGE, SEX, ID, NAME.
2、构建5条完全一样数据
insert into xiaoxu.sxiaoxu values(1,'xiaoxu',18,'m');
insert into xiaoxu.sxiaoxu values(1,'xiaoxu',18,'m');
insert into xiaoxu.sxiaoxu values(1,'xiaoxu',18,'m');
insert into xiaoxu.sxiaoxu values(1,'xiaoxu',18,'m');
insert into xiaoxu.sxiaoxu values(1,'xiaoxu',18,'m');
3、验证同步情况
3.1针对插入完全没有问题
--extract抽取情况
GGSCI 1> stats txiaoxu
Sending STATS request to EXTRACT TXIAOXU ...
Start of Statistics at 2019-04-03 21:17:22.
Output to ./dirdat/xu:
Extracting from XIAOXU.SXIAOXU to XIAOXU.SXIAOXU:
*** Total statistics since 2019-04-03 21:16:00 ***
Total inserts 5.00
Total updates 0.00
Total deletes 0.00
Total discards 0.00
Total operations 5.00
--replicat进程
GGSCI> stats rxiaoxu
Sending STATS request to REPLICAT RXIAOXU ...
Start of Statistics at 2019-04-03 21:18:43.
Replicating from XIAOXU.SXIAOXU to XIAOXU.TXIAOXU:
*** Total statistics since 2019-04-03 21:17:11 ***
Total inserts 5.00
Total updates 0.00
Total deletes 0.00
Total discards 0.00
Total operations 5.00
3.2 一次性更新全部5条数据,目标同样没有问题
update xiaoxu.sxiaoxu set name='xuxiao';
--检查源和目标数据完全一致的.对于源端5条更新,在目标更新都加上rownum=1来保证每次都更新一条.对logdump中类型是GGSPKUpdate.
通过打印SQL,目标端执行如下更新,set和where都加上所有列且where后面加上rownum=1来保证每次更新都是一条.
UPDATE "XIAOXU"."TXIAOXU" SET "ID" = '1',"NAME" = 'xuxiao',"AGE" = '18',"SEX" = 'm' WHERE "ID"='1' AND "NAME"='xiaoxu' AND "AGE"='18' AND "SEX"='m' AND ROWNUM = 1
Statement length: 164
(S)top display, (K)eep displaying (default):
3.3 源端随机更新一条,目标只能从第一条处理,只是顺序乱,但是数据是一致的.
--表数据以及rowid情况
比如把sxiaoxu中最后一条记录的name更新xiaoxu,目标其实是更新第一条.
update xiaoxu.sxiaoxu set name='xiaoxu' where rowid='AADwvrAAFAACEqkAAE';
commit;
目标表txiaoxu,是更新第一条数据
3.4 如果源表表结构发生,如是大字段会造成数据不一致问题.如是非大字段,必须重新删除附加日志,再次增加,否则会造成无法捕获增加列更新情况.
备注:针对大字段是无法加入到附加日志中.所以where中无大字段列,导致缺少一个列来判断重复值,导致更新异常.
alter table xiaoxu.sxiaoxu add (addresss clob);
alter table xiaoxu.txiaoxu add (addresss clob);
--重启抽取进程以及应用进程
--验证附加日志,发现附加日志并自动更新,需要重新删除后再增加,否则会造成extract无法捕获到新增列更新的情况.
GGSCI () > info trandata xiaoxu.sxiaoxu
Logging of supplemental redo log data is enabled for table XIAOXU.SXIAOXU.
Columns supplementally logged for table XIAOXU.SXIAOXU: AGE, SEX, ID, NAME.
【验证插入数据】
--验证源端插入数据,插入数据在最后一行
--验证目标插入数据,发现插入数据变成第一行
【验证更新数据】
--源端更新数据最后一条数据
update xiaoxu.sxiaoxu set addresss='newshanghai' where rowid='AADwvrAAFAACEqkAAF';
commit;
--目标检查数据--更新无异常
--源端更新数据第2条数据,name='xiaoxu'时,目标还是更新第一条数据.
update xiaoxu.sxiaoxu set addresss='oldshanghai1' where rowid='AADwvrAAFAACEqkAAE';
commit;
--目标检查数据--目标还是更新第一条数据,因为addresss附加日志没有捕获到.
3.5 如果源表表结构发生,增加是普通字段,如果没有删除附加日志,再次增加附加日志会造成什么问题,源端新加列,原来有值,更新其他字段时,会造成这个字段在目标被更新成NULL,这个坑,也会造成数据不一致,甚至丢失数据情况.
alter table xiaoxu.sxiaoxu add ( addresss varchar2(30));
alter table xiaoxu.txiaoxu add ( addresss varchar2(30));
--插入数据
如果抽取进程不重启,则捕获到空值.
INSERT INTO "XIAOXU"."TXIAOXU" ("ID","NAME","AGE","SEX","ADDRESSS") VALUES ('1','xiaojing1','18','m','')
Statement length: 106
如果抽取进程重启,则捕获到到正常值
INSERT INTO "XIAOXU"."TXIAOXU" ("ID","NAME","AGE","SEX","ADDRESSS") VALUES ('1','xiaojing2','18','m','shanghai')
Statement length: 114
--验证更新(重启抽取进程,trandata是没有这个字段)
update xiaoxu.sxiaoxu set name='newxiaojing3' where rowid='AADwvrAAFAACEqkAAJ';
commit;
select rowid,a.name,to_char(addresss) from xiaoxu.sxiaoxu a;
AADwvrAAFAACEqkAAJ newxiaojing3 shanghai
目标更新--发现源端地址变成空值了,因为附加日志问题导致的.如果更新地址这一列则没有问题,如果不更新地址这一列,直接变成NULL,注意这个坑。
UPDATE "XIAOXU"."TXIAOXU" SET "ID" = '1',"NAME" = 'newxiaojing3',"AGE" = '18',"SEX" = 'm',"ADDRESSS" = NULL WHERE "ID"='1' AND "NAME"='xiaojing3' AND "AGE"='18' AND "SEX"='m' AND "ADDRESSS" IS NULL AND ROWNUM = 1
Statement length: 214
3.6 如果使用keycols,keycols的值存在相同,但每一条记录所有字段组合是唯一的情况,如果存在2条记录,更新最后一条,如果源与目标记录顺序一致,那么更新会造成错误错误,如果记录顺序刚好相反,那么更新则没有问题.那么这个时候使用keycols是不合适的,没有达到标识唯一的记录,虽然速度会快些,还不如去掉keycols来保证数据完整性.
三【针对无主键无唯一索引的表,goldengate优化方案】
1、修改表结构,增加一个虚拟列使用sys_guid()函数来产生唯一值。这个需要考虑到表结构更改以及增加字段时间,对于新表增加影响会小,但是已存在大表,需要停机窗口来增加字段.
2、使用keycols来指定标识唯一值列(可以是多列),如果选出列无法满足,会出现如下情况
如果存在2条记录,更新最后一条,如果源与目标记录顺序一致,那么更新会造成错误错误,如果记录顺序刚好相反,那么更新则没有问题.那么这个时候使用keycols是不合适的,没有达到标识唯一的记录,虽然速度会快些,还不如去掉keycols来保证数据完整性.
3、无主键无唯一表,表结构发生变化,必须删除附加日志,再次增加附加(针对add trandata方式增加,如果是add schematrandata不存在这个问题),否则会出现数据丢失问题.
- Joomla 权限提升漏洞(CVE-2016-9838)分析
- Firefox - SVG cross domain cookie vulnerability
- 当代 Web 的 JSON 劫持技巧
- 利用特殊协议加载本地文件, 绕过 HTML5 沙箱, 打开弹窗诸事
- Nginx权限提升漏洞(CVE-2016-1247 )分析
- 初识 Fuzzing 工具 WinAFL
- 如何使用Oozie API接口向Kerberos环境的CDH集群提交Spark2作业
- 如何编译及使用TPC-DS生成测试数据
- ASP.NET MVC编程——缓存
- ASP.NET MVC编程——错误处理与日记
- Jenkins 未授权远程代码执行漏洞(CVE-2017-1000353)
- ASP.NET MVC编程——路由
- ASP.NET MVC编程——模型
- ASP.NET MVC编程——验证、授权与安全
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【React+Typescript+Antd】防止样式感染——LESS CSS 框架简介
- 【React+Typescript+Antd】界面框架布局——Layout布局+ Grid栅格
- SpringBoot源码学习(三)
- Axure RP 9 安装与中文汉化
- Linux 离线安装docker的过程
- Mac环境变量设置(以ADB为例)
- Linux 基础之定时任务
- Git库迁移步骤(从服务器A迁移至服务器B)
- springboot源码解析(四)
- 第2天:网易2018年校园招聘NLP算法工程师笔试试卷分析(二)
- Windows下Scoop安装、配置与使用
- Flutter免费iOS真机调试 AndroidStudio iPhone真机运行教程
- Flutter GridView 网格控件
- Flutter ListView 下拉刷新,上拉加载更多
- Flutter问题:import 'package:english_words/english_words.dart'失败