merge语句导致的ORA错误分析

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

时间: 2024-09-09 18:34:28

merge语句导致的ORA错误分析的相关文章

merge语句导致的CPU使用率过高的优化(二)

之前分享过一篇关于merge语句导致的CPU使用率过高优化的案例.的http://blog.itpub.net/23718752/viewspace-1819471/ 后续的跟进没有补充,也"秀"一张图,红色的火焰是原来的系统负载,右边的部分是最近的逻辑读情况,不过惭愧的是,这个不是优化的效果,因为应用的高峰期已经处理完了,后面的sql调用频率极低,所以感觉不到任何的压力.所以通过这个图也可以看出,给一张差别巨大的图也不一定是系统优化的效果,也可能是其它外在因素. 那么既然要说跟进,后

merge语句导致的性能问题紧急优化

晚上正在休息的时候,突然收到一封报警邮件. 报警内容: CPU utilization is too high ------------------------------------ 报警级别: PROBLEM ------------------------------------ 监控项目: CPU idle time:59.11 % ------------------------------------ 这个报警信息已经非常明确,CPU使用率很紧张了.这台服务器上运行着Oracle和M

merge语句导致的CPU使用率过高的优化

今天有一个数据库有点反常,早上的时候报出了CPU使用率的警告. 警告内容如下: ZABBIX-监控系统: ------------------------------------报警内容: CPU utilization is too high ------------------------------------报警级别: PROBLEM ------------------------------------监控项目: CPU idle time:44.61 % -------------

一条sql语句导致的数据库宕机问题及分析

之前分享过一篇博文,是一条sql语句"导致"的数据库宕机,上次是另有原因,这次真碰到一个案例,而且是在重要的环境上,希望大家引以为戒. 数据库是基于Linux64的版本,版本是11.2.0.2.0,已经打了最新的psu. 数据库的访问用户数大约在1000左右,当时查看服务器的cpu已经是100%了,有大约10个进程都是cpu 100%,数据库逻辑读也是超高,一秒钟大约是接近百兆的情况,sga是12G,已用了sga的自动管理(sga_target=0), 查看内存组件时发现buffer_

SQL Server中使用 Merge 语句实现表数据之间的对比同步

表数据之间的同步有很多种实现方式,比如删除然后重新 INSERT,或者写一些其它的分支条件判断 再加以 INSERT 或者 UPDATE 等.包括在 SSIS Package 中也可以通过 Lookup, Condition Split 等多 种 Task 的组合来实现表数据之间的同步.在这里 "同步" 的意思是指每次执行一段代码的 时候能够确保 A 表的数据和 B 表的数据始终相同. 可以通过 SQL Server 中提供的 Merge 语句来实现,并且还可以将操作的细节记录下来.具

c语言-迷宫问题出现死循环,经调试发现似乎为结构体中数据无法改变,又或者其他语句导致?

问题描述 迷宫问题出现死循环,经调试发现似乎为结构体中数据无法改变,又或者其他语句导致? #include #include typedef struct//定义栈元素结构类型 { int x; int y; int direction; }data; typedef struct//定义栈 { data *base; data *top; int stacksize; }sqstack; int initstack(sqstack &s)//建立栈 { printf("please i

如何理解T-SQL中Merge语句

原文:如何理解T-SQL中Merge语句 写在前面的话:之前看过Merge语句,感觉没什么用,完全可以用其他的方式来替代,最近又看了看Merge语句,确实挺好用,可以少写很多代码,看起来也很紧凑,当然也有别的优点. ====正文开始===== SQL Server 2008 引入了Merge关键字,主要是在一条语句里面可以执行insert.update.delete操作,以实现用一个源对象的数据对目标对象数据进行操作.注意这里的"源对象"和"目标对象"我用黑色标注了

MySQL中实现插入或更新操作(类似Oracle的merge语句)_Mysql

如果需要在MySQL中实现记录不存在则insert,不存在则update操作.可以使用以下语句: 更新一个字段: INSERT INTO tbl (columnA,columnB,columnC) VALUES (1,2,3) ON DUPLICATE KEY UPDATE columnA=IF(columnB>0,1,columnA) 更新多个字段: INSERT INTO tbl (columnA,columnB,columnC) VALUES (1,2,3) ON DUPLICATE KE

SQL Server使用Merge语句当源表数据集为空时,无法进行查询的问题_MsSql

面举一个例子来具体说明一下: 有两个表SourceTable为登陆表,TargetTable为授权表,如果访问用户在登陆表中,更新授权表的授权级别,否则授权0表示游客.sql语句如下: --SourceTable为登陆表,TargetTable为授权表 --如果访问用户在登陆表中,更新授权表的授权级别,否则授权0表示游客. create table SourceTable(UserName nvarchar(10),Pwd int,[Level] int) create table Target