oracle挂证多少钱一个月_惊呆,一条sql竟然把Oracle搞挂了

一条sql就能把oracle搞挂了,真的是不敢相信啊,前几天生产上确实出现了这样一个故障,我们来一起做一个事件回放。

系统介绍

系统架构见下图:

818ea8c2e63f

file

application1和application2是一个分布式系统中的2个应用,application1连接的数据库是database1,application2连接的数据库是database2,application2生产的数据要给application1做跑批使用。

application1要获取database2的数据,并不是通过接口来获取的,而是直连database2来获取,因此application1也具有database2库的读权限。

database2中有1张表table_b,里面保存的数据是application1跑批需要的数据。application1查找到table_b的数据后,先保存到database1的数据库表table_a中,等跑批时取出来用。

table_a和table_b的表结构如下:

818ea8c2e63f

file

2个表的主键都是字段a,application1查询出table_b的数据后,会根据主键a来判断这条数据是否存在,如果数据存在,就更新,否则,就插入。

application1使用的orm框架是mybatis,为了减少应用和数据库的交互,使用了oracle的merge语句。

注意:mybatis相关的文件有5个:

TableAMapper.java

TableBMapper.java

TableAMapper.xml

TableBMapper.xml

TableAEntity.java

熟悉mybatis的同学应该都知道,前两个java类是sql操作接口类,第3、4两个文件是存放sql的xml文件,跟前两个文件对应,最后一个java文件是do类。

事故现场

TableBMapper中有一个方法selectForPage,用来按页查询table_b中数据,每页1万条数据,之后把这个list结果merge到table_a,看一下代码:

//从table_b按每页1万条来查询数据

List list = tableBMapper.selectForPage(startPage, 10000);

//把查到的数据一次性merge到table_a中

tableAMapper.mergeFromTableB(list);

我们再看一下TableAMapper.xml中的mergeFromTableB方法,代码如下:

MERGE INTO table_a ta USING(select #{item.a} as a,#{item.b} as b,#{item.c} as c, #{item.d} as c from dual) tb

on (ta.a = tb.a)

WHEN MATCHED THEN UPDATE set

ta.b=tb.b,

ta.c=tb.c,

ta.d=tb.d

WHEN NOT MATCHED THEN insert(

a,

b,

c,

d

)

values (

tb.a,

tb.b,

tb.c,

tb.d

)

注意:为了文章排版,我对表结构做了简化,真实案例中table_a这张表有60多个字段。

这条sql执行后,我截取部分oracle的日志,如下:

818ea8c2e63f

file

图中可以看到oracle报了ORA-07445错误。

分析日志后发现,sql绑定变量达到了了79010个,而oracle是不允许超过65535个的。

解决方案

前面的分析确定了导致oracle挂掉的原因是绑定变量超过了65535个,那对症下药,解决的方案有3个:

业务系统方案

1.循环单条执行merge语句,优点是修改简单,缺点是业务系统跟数据库交互太多,会影响跑批任务执行效率。

2.对mergeFromTableB进行分批调用,比如每1000条调用一次merge方法,改造稍微多一点,但是交互会少很多。

DBA方案

给oracle打一个补丁,这个方案需要停服务。

业务方案2明细有优势,我用这个方案进行了改造,每次1000条,批量merge,代码如下:

for (int i = 0; i < list.size(); i += 1000) {

if (i + 1000 < list.size()) {

tableAMapper.mergeFromTableB(list.subList(i, i + 1000));

} else {

tableAMapper.mergeFromTableB(list.subList(i, list.size()));

}

}

新的问题

按照上面的方案改造完成后,数据库不会奔溃了,但是新的问题出现了。测试的同学发现,每次处理超过1000条数据,非常耗时,有时竟然达到了4分钟,惊呆。

看打印的批量sql,类似于下面的语句:

begin

merge into table_a ta USING(...;

merge into table_a ta USING(...;

end;

分析了一下,虽然放在了一个SQL块中,但还是单条执行,最后一起提交。

再做一次优化,把上面多条merge语句合成1条。

我的优化思路是创建一张临时表,先把list中的数据插入到临时表中,然后用一次merge把临时表的数据merge进table_a这张表。

oracle的临时表有2种,一种是会话级别,一种是事务级别:

会话级别的临时表,数据会在整个会话的生命周期中,会话结束,临时表数据清空;

事务级别的临时表,数据会在真个事务执行过程中,事务结束,临时表数据清空。

下面看具体实施过程。

1.我们创建一张会话临时表,SQL如下:

create global temporary table_a_temp on commit delete rows as select * from table_a;

comment on table_a_temp is 'table_a表临时表';

2.把table_b查询到的数据list插入临时表,需要在 TableAMapper.xml 增加一个方法:

insert all

into table_a_temp

a,

b,

c,

d,

#{item.a},

#{item.b,jdbcType=VARCHAR},

#{item.c,jdbcType=VARCHAR},

#{item.d,jdbcType=VARCHAR},

select 1 from dual

注意:oracle的insert all语句单次插入不能超过1000条。

3.把临时表的数据merge到table_a中,需要在 TableAMapper.xml 增加一个方法:

MERGE INTO table_a ta

USING (select * from table_a_temp) tb

on (ta.a = tb.a)

WHEN MATCHED THEN UPDATE set

ta.b = tb.b,

ta.c = tb.c,

ta.d = tb.d

WHEN NOT MATCHED THEN

insert

(a, b, c, d)

values

(tb.a, tb.b, tb.c, tb.d)

4.最终业务代码修改如下:

//从table_b查询

List list = tableBMapper.selectForPage(startPage, 10000);

//批量插入table_a_temp临时表

for (int i = 0; i < list.size(); i += 1000) {

if (i + 1000 < list.size()) {

tableAMapper.batchInsertTemp(list.subList(i, i + 1000));

} else {

tableAMapper.batchInsertTemp(list.subList(i, list.size()));

}

}

//从table_a_temp把数据merge到table_a

tableAMapper.mergeFromTempData();

总结

在oracle上执行SQL时,如果绑定变量的数量超过了65535,会引发ORA-07445。当然,引发ORA-07445的原因还有其他。

解决这个问题最好的方式是从业务代码层面进行修改。

也可以让DBA可以给oracle打一个补丁,但是oracle必须要停服务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298999.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux图形界面鼠标变成小手_加载Linux系统,树莓派变身桌面电脑

开始正文前&#xff0c;我们想听听娃说了什么操作系统&#xff0c;英文名叫做Operation System&#xff0c;简写为OS&#xff0c;是电子设备运行的基础软件&#xff0c;按运行的设备类型来分&#xff0c;操作系统分为手机操作系统&#xff0c;桌面电脑操作系统和服务器操作系统…

二叉查找树转换成有序的双向链表

首先对于二叉查找树的定义和性质&#xff0c;以及如何得到二叉查找树某个节点的子树下的最大值和最小值和插入一个值的内容可以参考这两篇文章&#xff1a; &#xff08;1&#xff09;http://www.cnblogs.com/chenping-987123/archive/2010/09/25/1834341.html &#xff08;2&a…

就你这个求婚态度,能嫁给你才怪!

1 兄弟&#xff01;哪有求着婚还走神的&#xff1f;&#xff01;▼2 喝奶茶专用口罩&#xff01;▼3 把广东茶楼的菜都点一遍是什么体验&#xff1f;▼4 你觉不觉得这个门锁有点像托马斯的小火车▼5 手里的塑料袋像极了塑料兄弟情▼6 小朋友看《喜羊羊》看到的是坏人的愚…

Remoting and MSMQ 结合做的一个DEMO

真的非常感谢CnBlogs.com,因为有很多教程里写的知识点并不全面,而且也没附带例子.通过这里我学习到了很多很多.希望网站能越办越好哦.下面是我学习分布式开发时写的一个小demo,当然功能有限,技术也很低.希望大师们能拍拍砖,不吝赐教.呵呵软件运行的一个截图下面说说流程吧,1:利…

再聊一次值类型和引用类型

C#值类型&#xff0c;作为函数形参&#xff0c;形参被修改&#xff0c;不影响原值。这是我们在初始学习编程时需要记住的内容&#xff0c;我们也是一直这样践行的。先说结论&#xff1a;这是不准确的。为什么提出这样看似很浅显的问题&#xff0c;是因为有次我在使用ArraySegme…

java+字节码工具64位_jclasslib 下载-jclasslib 32位64位(java字节码查看工具) 5.1 官方版 - 河东下载站...

jclasslib是款免费的开源java字节码的查看工具&#xff1b;它支持进行查看您需要进行使用汉字运用到的Java字节码&#xff0c;并且还拥有一个的类库来让开发者进行读取&#xff0c;包括了修改、对JavaClass文件、字节码的写入等&#xff1b;用户这进行使用的过程中&#xff0c;…

ado filter 多条记录_注意!武汉江南中心绿道武九线综合管廊工程开工,青山区多条道路通行规则有变...

楚天都市报10月29日(记者吴昌华 通讯员 李佳 陈菲)今日记者从武汉交管部门获悉&#xff0c;本周六&#xff0c;10月31日&#xff0c;武汉市江南中心绿道武九线综合管廊工程开始施工&#xff0c;青山区多条道路通行规则有变&#xff0c;部分道路禁止通行。交管部门提供详细绕行建…

深度学习框架再次升级,它们都有什么优点?

全世界只有3.14 % 的人关注了爆炸吧知识经过几年的发展&#xff0c;深度学习方法摧枯拉朽般地超越了传统方法&#xff0c;成为人工智能领域最热门的技术。之后&#xff0c;谷歌、亚马逊、百度、Facebook 纷纷开源了自己的深度学习框架。而支撑AlphaGo的核心技术架构--TensorFlo…

SQL Server 2005的安装,SQL Server 2005系列之一

最近复习SQL Server 2005,忽然有了写系列的打算&#xff0c;也不知道能不能写好&#xff0c;今天先写一篇关于SQL Server 2005的安装的博文吧。和往常一样&#xff0c;我们先来看看SQL Server 2005到底是个什么东西&#xff1f;SQL Server 2005是一种以高性能、高可靠性和可用性…

Quartz - 作业调度框架-插件化开发

背景大部分业务都是基于定时的任务&#xff0c;特别适合使用quartz这类框架解决定时问题。具体quartz的使用&#xff0c;看官方文档就可以了。下面谈谈对quartz插件化的封装。我们使用quartz.plugin。然后在quartz_jobs.xml方法里面定义了schedule&#xff0c;其中灵活的地方在…

cgi备份还原和ghost有什么区别_手动GHOST还原重装系统详细教程

一键重装虽好&#xff0c;但也不是万能的。俗语说&#xff1a;治标不治本。也许你懂得用各种一键备份还原工具重装&#xff0c;但不一定懂得手动GHOST重装。为此&#xff0c;吻妻为大家分享一下如何手动GHOST还原重装系统&#xff0c;本教程步骤虽多&#xff0c;但很多都是点“…

图解一步步安装SharePoint Foundation 2010

图解一步步安装SharePoint Foundation 2010 下载后在Windows Server 2008 R2上进行安装安装产品必须的一些组件&#xff0c;比原来好多了不用自己一个个下了。同意许可&#xff0c;此产品为不收费版本&#xff0c;不用序列号了&#xff01;&#xff01;&#xff01;安装相关的…

MYSQ 查看 2 进制日志

方法 1&#xff1a; myqlbinlog filename; -----------------------------------------------------------------------------------------------------------------------------------------------

当身为老师的爸爸上课时......​

1 当身为老师的爸爸上课时......▼2 气氛突然微妙......▼3 隔壁的一家人都馋哭了&#xff01;▼4 结束疫情隔离的你▼5 WOW!AMAZING!▼6 女孩子喜欢帅哥是不分年龄的▼‍‍7 单身狗又做错了什么呢&#xff1f;▼你点的每个赞&#xff0c;我都认真当成了喜欢

amos里CFA可行性辨别结果怎么看_论文用问卷调查法,数据分析怎么做?

论文问卷数据的分析&#xff0c;看起来简单&#xff0c;好像每个人都会做。但是做起来还真的有点难度。很多初次使用问卷调查方法的人大多以为&#xff0c;问卷数据分析嘛&#xff0c;无外乎对单选题做做频率分析&#xff0c;看看选择不同的选项的人占比有多少。对于评分题目&a…

Hello Blazor:(10)按需加载JavaScript脚本

前言Blazor支持执行JavaScript脚本&#xff0c;通常是将脚本放在wwwroot/index.html(Blazor WebAssembly)或Pages/_Host.cshtml(Blazor Server)中。但是&#xff0c;这种方式会将所有JS方法用全局函数加载&#xff0c;即使某些方法只需要在特定组件中使用。既影响加载性能&…

只有学霸才懂的学习技巧,看完脑洞大开,绝对涨姿势!

▲ 点击查看法国生物学家乔治.居维叶曾说&#xff1a;“天才&#xff0c;首先是注意力。”事实上&#xff0c;除开那些逆天的天才之外&#xff0c;大部分人的智商&#xff0c;在先天因素的决定下&#xff0c;都是差不多的。但是专注力却可以因为后天的刻意训练&#xff0c;而有…

解析邻居的耳朵音乐地址(单页下载)

偶尔听歌的时候发现了一个很小众的音乐分享网站&#xff0c;邻居的耳朵&#xff0c;有个人的电台类型&#xff0c;属于音乐分享文字分享&#xff0c;觉得很不错。从域名来看&#xff0c;属于多米旗下的网站&#xff1a;http://ear.duomi.com/ 看来多米收购了很多这样的小站&am…

为什么电脑不能打字_嘉兴在线丨「生活经济学」为什么笔记本电脑能在任何国家的供电标准下运作,其他大部分电器却不能?...

【生活热搜】从日本背回来的电饭煲煮饭口感总是不对&#xff0c;用几天就坏了&#xff1b;英国邮回来的吹风机怎么都插不上电源只能闲置……如果你有从国外买家用电器的经历&#xff0c;你一定会发现很多电器因为每个国家或地区的供电标准不同而无法正常使用的情况。但笔记本电…

【DotNetMLLearn】.NET Core 人工智能系列-.NET Interactive环境介绍

在进入.NET Core 的人工智能应用开始前&#xff0c;我们先把环境搭建好&#xff0c;为以后的学习提供一个便利。作为一个.NET 程序员&#xff0c;或者其他编程语言的程序员&#xff0c;相信对IDE的依赖必不可少&#xff0c;如Visual Studio/Visual StudioCode , IntelliJ , Ecl…