博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
merge语句导致的ORA错误分析
阅读量:2446 次
发布时间:2019-05-10

本文共 2861 字,大约阅读时间需要 9 分钟。

      最近处理了好几起关于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工作笔记》已开售,在京东,当当,亚马逊,淘宝,天猫均有售,欢迎选购。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23718752/viewspace-2122373/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/23718752/viewspace-2122373/

你可能感兴趣的文章
12个令人难以置信的CodePen.IO演示
查看>>
css 实现动画折叠展开_CSS 3D折叠动画
查看>>
做了磁盘阵列的硬盘如何恢复_从自制软件恢复磁盘空间
查看>>
post 重复参数_参数名称重复
查看>>
保存到VS Code后如何修复ESLint错误
查看>>
Object.fromEntries
查看>>
mongdb选择存储引擎:_选择引擎:从右到左
查看>>
pubg 接口在哪里_如何在PUBG中获取绿血
查看>>
node压缩css_Node.js CSS压缩器:clean-css
查看>>
JavaScript CSS助手
查看>>
邪恶的AJAX:使用jQuery的Spyjax
查看>>
css指针悬停_CSS指针事件
查看>>
目标检测 多分辨率检测_检测视频分辨率
查看>>
python 获取类方法_使用Python获取类方法
查看>>
mac dock 隐藏程序_从Dock删除最近的应用程序
查看>>
console.timeLog
查看>>
替换命令 shell_替换Shell中的最后一个命令
查看>>
ip校验和 tcp校验和_如何校验和
查看>>
numpy数组与布尔数组_数组和布尔
查看>>
Firefox Marketplace动画按钮
查看>>