merge语句导致的ORA错误分析

简介:       最近处理了好几起关于merge导致的问题,其实看到merge语句内心也还是蛮纠结的,这一次还是碰到了问题,简直无语了。       先交代下问题的背景。有一套OLTP环境和OLAP环境需要同步一部分数据,都是在每天的半夜开始,OLAP的库的一个表数据会根据增量的逻辑从OLTP库中同步,有两种方式,一种是OLAP从OLTP中去抓取,另外一种是OLTP推送给OLAP。
      最近处理了好几起关于merge导致的问题,其实看到merge语句内心也还是蛮纠结的,这一次还是碰到了问题,简直无语了。
      先交代下问题的背景。有一套OLTP环境和OLAP环境需要同步一部分数据,都是在每天的半夜开始,OLAP的库的一个表数据会根据增量的逻辑从OLTP库中同步,有两种方式,一种是OLAP从OLTP中去抓取,另外一种是OLTP推送给OLAP。看起来表达的意思是差不多的,实现起来就是完全不同的风格,即一种主动一种被动,而对于大部分的应用需求来看,还是更倾向于OLAP从OLTP中去抓取这种方式,要不OLTP端还是存在一定的耦合度。
    

     但是目前的情况是OLTP主动推送给OLAP,当然这种设计方式看来达到的效果都是一致的,而且因为历史原因,也是一直这么用的。
在一次升级以后,借着升级的机会,而且很巧又碰到了老版本兼容merge语句的问题(又是merge),所以就自然而然想一并做个改进,把这个问题规范起来。
改进以后,OLAP会从OLTP中抓取数据,原来的逻辑完全不用修改,只是在两个表关联的地方,使用到了DB link来处理,所以代码层面可以认为是没有其它的变化,而且在部署到OLAP端后,我创建了一个小表还测试了一把,没有发现问题,所以简单修改配置之后,就部署完成了,还给开发的同事讲解了这个改进的意义,自己也还是蛮高兴的。
    第二天同事就主动找我,说增量数据没有同步过来,带着程序员最常用的口吻“不可能啊”,“我这里运行都好好的”之类的想法,我查看了后台的JOB运行日志,结果发现日志中竟然抛出了一个ORA错误。
ORA-30926: unable to get a stable set of rows in the source tables
ORA-06512: at line 32
这个错误看起来似懂非懂,比较模糊,初步感觉是表结构哪里出现了不一致的情况。
实现的大体思路如下:
insert into test.tmp_usercenter select *from xxx@OLAP where xxxx; --通过这种方式获得增量数据
然后把增量数据插入test.test_user_center中。不匹配则插入
merge into test.test_user_center a
using (select * from tlbb.tmp_usercenter) b
on (a.uin=b.uin)
when matched then
update set LAST_LOGOUT=b.LAST_LOGOUT,
LAST_IP=b.LAST_IP,
FIRST_GAMESTYLE=b.FIRST_GAMESTYLE
when not matched then
insert (CN,
UIN,
BILL_TYPE,
PRESENT_POINT,。。。
OUTLINE_SCORE,FIRST_GAMESTYLE)
values
(
b.CN,
b.UIN,
b.BILL_TYPE,
b.PRESENT_POINT,。。。
b.FIRST_GAMESTYLE);
commit;
了解了大体的思路之后,我对里面涉及的历史表字段都进行了认真的比对,没有发现任何问题,增量的数据都进行了比对,都是和原来的生成方式一样的。
但是为什么这种方式就会出问题呢。这一点上我不好解释,也不好给其他人解释,所以我需要认真分析,看看到底是哪里的问题。
同时我认真比对了ORA-30926错误的解释,发现merge在处理一些DML的时候,如果同一记录被影响变更多次,则会出现这类问题,那也就意味着表中的数据有冗余的成分。
但是同样的数据,同样的逻辑,几乎同样的语句,怎么原来可以,现在不可以呢。
最后反复测试,发现原来还是DB link在这一点上有很大的差别,如果在正常情况下存在冗余数据或者重复数据的情况下,使用merge来更新是会抛出ORA-30926错误的。而使用DB Link竟然会把这个错误化解,而一直以来使用的在OLTP端推送数据至OLAP,在这个场景下使用了这样的方式,看似也是碰到了一些问题,最后采用的那种方式,我不知道之前的人是否意识到那个问题,或者可能认为那种方式不支持这种需求,而我在尝试改进的时候,就踩到了这个坑。当然我还是希望能够在OLAP端完成这个需求,而原来可以,我们就可以借鉴成功的思想,所以改进起来就是耍个小聪明。DB link可以绕过这个ORA错误,那我们就使用DB link,但是访问的是当前库的表数据。即我们创建一个DB link指向自己,然后通过DB Link的方式访问。这样反复测试,发现确实是可以的。
所以语句的逻辑就改为下面的形式:
insert into test.tmp_usercenter select *from xxx@OLAP where xxxx; --通过这种方式获得增量数据
然后把增量数据插入test.test_user_center中。不匹配则插入
merge into test.test_user_center@OLAP_TEST a   --创建一个DB link OLTP_TEST指向当前的数据库
using (select * from tlbb.tmp_usercenter) b
on (a.uin=b.uin)
when matched then
update set LAST_LOGOUT=b.LAST_LOGOUT,
LAST_IP=b.LAST_IP,
FIRST_GAMESTYLE=b.FIRST_GAMESTYLE
when not matched then
insert (CN,
UIN,
BILL_TYPE,
PRESENT_POINT,。。。
OUTLINE_SCORE,FIRST_GAMESTYLE)
values
(
b.CN,
b.UIN,
b.BILL_TYPE,
b.PRESENT_POINT,。。。
b.FIRST_GAMESTYLE);
commit;
这种方式能够改进原来的ORA错误,权当做一种变相的改进吧。

#############################

每日发文,或技术、或总结,偶有日间小事也以为记,谓之学习笔记,成年累月800多天,中间几乎没有间断,要旨只有一个:学习交流,共同进步 。

#############################

学习笔记精华整理,个人新书《Oracle DBA工作笔记》已开售,在京东,当当,亚马逊,淘宝,天猫均有售,欢迎选购。


相关实践学习
数据库实验室挑战任务-初级任务
本场景介绍如何开通属于你的免费云数据库,在RDS-MySQL中完成对学生成绩的详情查询,执行指定类型SQL。
阿里云云原生数据仓库AnalyticDB MySQL版 使用教程
云原生数据仓库AnalyticDB MySQL版是一种支持高并发低延时查询的新一代云原生数据仓库,高度兼容MySQL协议以及SQL:92、SQL:99、SQL:2003标准,可以对海量数据进行即时的多维分析透视和业务探索,快速构建企业云上数据仓库。 了解产品 https://www.aliyun.com/product/ApsaraDB/ads
目录
相关文章
|
7月前
|
Python
使用`merge`函数将两个dataframe合并在一起,然后使用`query`函数根据指定的条件选取数据
在pandas中,可以使用`merge`函数将两个dataframe合并在一起,然后使用`query`函数根据指定的条件选取数据。
83 1
提高group by语句的效率
提高group by语句的效率
|
SQL 数据库管理
【SQL开发实战技巧】系列(九):一个update误把其他列数据更新成空了?Merge改写update!给你五种删除重复数据的写法!
本篇文章讲解的主要内容是:***你有没有经历过一个update把其他列数据清空了、使用merge更新合并记录、删除违反参照完整性的记录、给你五种删除重复数据的写法*** 【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。
【SQL开发实战技巧】系列(九):一个update误把其他列数据更新成空了?Merge改写update!给你五种删除重复数据的写法!
九、提高group by语句的效率
九、提高group by语句的效率
288 0
|
数据库 开发者 索引
merge 操作|学习笔记
快速学习 merge 操作
172 0
merge 操作|学习笔记
|
SQL 数据挖掘 数据库
DataFrame多表合并拼接函数concat、merge参数详解+代码操作展示
DataFrame多表合并拼接函数concat、merge参数详解+代码操作展示
647 0
DataFrame多表合并拼接函数concat、merge参数详解+代码操作展示
|
SQL 存储 缓存
执行update语句,用没用到索引,区别大吗?
我们都知道,当执行 select 查询语句时,用没用到索引区别是很大的,若没用到索引,一条 select 语句可能执行好几秒或更久,若使用到索引则可能瞬间完成。那么当执行 update 语句时,用没用到索引有什么区别呢,执行时间相差大吗?本篇文章我们一起来探究下。
351 0
|
SQL 缓存 算法
写出好的Join语句,前提你得懂这些
因为驱动结果集越大,意味着需要循环的次数越多,也就是说在被驱动结果集上面所 需要执行的查询检索次数会越多。比如,当两个表(表 A 和 表 B) Join 的时候,如果表 A 通过 WHERE 条件过滤后有 10 条记录,而表 B 有 20 条记录。如果我们选择表 A 作为驱动表,也就是被驱动表的结果集为 20,那么我们通过 Join 条件对被驱动表(表 B)的比较过滤就会有 10 次。反之,如果我们选择表 B 作为驱动表,则需要有 20 次对表 A 的比较过滤。小贴士1:驱动表的定义:当进行多表连接查询时,1.指定了联接条件时,满足查询条件的记录行数少的表为驱动表,2.未指定联接条件时,行数少
|
SQL 数据库
|
SQL 监控 关系型数据库
index_merge导致死锁案例分析
一、死锁现象描述 1.1 基本环境信息 1、数据库版本以及隔离级别 mysql>select version(); +---------------------+ | version() | +---------------------+ | 5.
1066 0

热门文章

最新文章