Part1 环境信息
源库和目的库都是Oracle 11GR2
Part2 问题信息
目的库创建模拟表
create table A_test(
id nvarchar2(200),
name nvarchar2(200),
age integer,
password nvarchar2(200)
);
alter table A_test add constraint A_test_id primary key (id,name);
-- 插入1000的模拟数据
INSERT INTO A_test (id, name, age, password)
SELECT
'id'||FLOOR(DBMS_RANDOM.value(0, 10000)), -- 生成随机的ID
'User'||FLOOR(DBMS_RANDOM.value(0, 10000)), -- 生成随机的用户名
FLOOR(DBMS_RANDOM.value(18, 118)), -- 生成随机的年龄 (18-117)
'user'||FLOOR(DBMS_RANDOM.value(0, 10000)) ||'@example.com'-- 生成随机的邮箱地址
FROM
dual
CONNECT BY LEVEL <=1000;
模拟创建源库的抽取表,
我一般是通过数据泵来迁移这个表,这里只是模拟
create table B_test as select * from A_test;
模拟A_test缺数
delete from A_test where rownum < 200;
commit;
select count(*) from A_test;
801
select count(*) from B_test;
1000
Part3 问题模拟
3.1、OGG定位源库目的库信息
登录OGG
./ggsci
查看所有信息OGG进程信息
GGSCI () 1> info all
查看连接信息group
GGSCI () 1> view params ECA2
定位带table的行,确认有需要同步的问题表
找到问题表再找连接数据库信息
GGSCI () 1> view params ECA2
userid 用户@tns信息, password 密码
找到userid开头的行,通过@后边的关键字
find / -name tnsnames.ora
cat tnsnames.ora
通过目的端的info进程来判断源端的进程数据库信息
3.2、OGG定位源库目的库信息
直接问业务人员也行
Part4 问题解决
4.1、IGNORE_ROW_ON_DUPKEY_INDEX倒数(适合不超过2千万的数据)
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(A_test(id,name)) parallel(16) */
INTO A_test
select * from B_test;
commit;
模拟两表列不一致的情况,记得把列写清楚
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(A_test(id,name)) parallel(16) */
INTO A_test
select id,name,age,password from B_test;
commit;
比较数量,如果数量不对,还可以在执行几次
select count(*) from A_test;
1000
4.2、NOT EXISTS倒数(两个表分别的数据超过2千万)
再次模拟删除数据
delete from A_test where rownum < 200;
commit;
创建缺数据备份表
CREATE TABLE B_test_bak AS
SELECT B_test.*
FROM B_test
WHERE NOT EXISTS (
SELECT 1
FROM A_test
WHERE A_test.id = B_test.id
AND A_test.name = B_test.name
);
这样插入
INSERT INTO /*+ parallel(8) */ A_test
select * from B_test_bak;
commit;
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(A_test(id,name)) parallel(16) */
INTO A_test
select id,name,age,password,sysdate from B_test;
commit;
必须要这么做,因为当表的数据量很大的时候,不管是检索的时间长,还是undo表空间,都无法承受这样的消耗负担。 我在生产库尝试直接用IGNORE_ROW_ON_DUPKEY_INDEX插入数据,导致62G得undo表空间都不够用了。
Part5 原理
在Oracle数据库中,MINUS 操作符用于返回两个查询结果之间的差异。具体来说,它返回第一个查询中存在而第二个查询中不存在的行。这在你需要找出一个数据集与另一个数据集之间的差异时非常有用。
IGNORE_ROW_ON_DUPKEY_INDEX:忽略唯一约束冲突,回滚当前行(这个是导致UNDO表空间增长的主要原因),继续完成其他行的插入。
Part6 题外话
AI建议我用 minus、left join和not exist,但是感觉minus的局限性比较强,做列少的表,比较合适,而且要熟悉表信息,个人感觉不太实用。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




