写了一个分页 sql,因为粗心出了 bug 造成了 OOM!

news2024/9/23 12:27:50

大家好,我是君哥。

最近上完线后,凌晨收到一个生产告警,一个 OOM 异常导致了服务重启。今天来分享一下这个事故。

1.事故现场

事故的代码逻辑并不复杂,从一个大概有 8 万数据的表里面查出数据,汇总后对数据做处理。因为数据量有 8 万,这里做了分页查询,每页查询 1000 条。这里贴一下代码:这里我们假定这个表名叫 sql_bug。

private void testSQLBug(){
 List<SQLBugData> sqlBugDatas = new ArrayList<>();
 int pageSize = 1000;
 int pageNumber = 0;
 while (true){
  List<SQLBugData> data = sqlBugDataMapper.queryData(pageSize, pageNumber);
  if (CollectionUtils.isEmpty(data)){
   break;
  }
  //过滤掉不符合条件的数据。
  filterData(data);
  sqlBugDatas.addAll(data);
  if (data.size() <= pageSize){
   break;
  }
  pageNumber++;
 }
}

下面我们看一下 sql,这里用 Oracle 数据库,orm 框架用的 mybatis,sql 在 mapper.xml 文件中:

select * from sql_bug order by id
offset #{pageNumber} rows fetch first #{pageSize} rows only

仔细看上面的 sql,我们可以看到 Offset 这个参数传入了 pageNumber。那后果是什么呢?查询语句每次偏移量加 1,表里有 8 万条数据,相当于得查询 79000 次循环才能结束。sqlBugDatas 数据量一直累加,最终触发 OOM。

2.原因分析

开发同事为什么会出这个 bug 呢?原因是错误地把 offset 这个变量理解成是页码的偏移量。正确的写法:

select * from sql_bug order by id
offset #{pageNumber}*#{pageSize} rows fetch first #{pageSize} rows only

为什么测试没有测出来呢?测试环境数据量比较小,并没有出现 OOM 的情况。

代码 review 为什么没有发现?由于交付的代码量很大,做代码 review 的同事主要关注点在业务逻辑的正确性上面,并没有精力能看到这么细节的问题。

3.分页写法

使用 offset 进行分页的写法很常见,比如使用 MySQL 的 limit 语法,sql 如下:

select * from sql_bug order by id
limit #{pageNumber}*#{pageSize},#{pageSize}

但是使用 Offset 进行分页的写法并不推荐,因为有深度分页的性能问题,后面的页耗时会越来越多。下图是阿里开发手册关于分页场景的一个规范。

图片

遵循这个规范,我们每次查询的时候,不妨传入一个主键 id。先改写一下代码:

private void testSQLBug(){
 List<SQLBugData> sqlBugDatas = new ArrayList<>();
 String id = null;
 int pageSize = 0;
 while (true){
  List<SQLBugData> data = sqlBugDataMapper.queryData(id, pageSize);
  if (CollectionUtils.isEmpty(data)){
   break;
  }
  id = data.get(data.size()-1).getId();
  //过滤掉不符合条件的数据。
  filterData(data);
  sqlBugDatas.addAll(data);
  if (data.size() <= pageSize){
   break;
  }
 }
}

配合上面代码,把 sql 也改写一下,这里使用 mysql 语法:

select * from sql_bug 
<if test="id != null">            
 where id <![CDATA[>]]> #{id}
</if>   
order by id
limit #{pageSize}

也可以使用 rownum 来控制,下面再改写一下(Oracle 语法):

select * from(
 select * from sql_bug 
 <if test="id != null">            
  where id <![CDATA[>]]> #{id}
 </if>   
 order by id
)
where rownum <![CDATA[<]]> #{pageSize} + 1

我个人更推荐 rownum 写法,原因有 2 个:

  1. 这种语法更容易理解,如果出问题的 sql 使用这个语法,大概率是不会出这个 bug 的;

  2. 国内好多公司做信创改造,国产数据库对这种语法支持更好一些。

4.总结

本文介绍了一个生产事故,并对事故和改进方法进行了分析,希望对你理解数据库分页有所帮助。

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

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

相关文章

高校宣讲会管理系统--论文pf

TOC springboot370高校宣讲会管理系统--论文pf 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔记本的…

【myz_tools】Python库 myz_tools:Python算法及文档自动化生成工具 - 0.2.0版更新

文章目录 0.2.0 更新内容如下函数generate_2d_combinations_iter函数generate_row_permutations函数calculate_total_permutations函数display_combinations函数evaluate_list_similarity函数check_unique 写在前面关于库库使用库内所有函数目录文件名称: common_maths.py函数部…

ZooKeeper分布式协调系统介绍

1. ZooKeeper概述 1.1 ZooKeeper介绍 ZooKeeper 是 Apache 软件基金会的一个项目&#xff0c;它确实提供了一种非常有用的服务&#xff0c;用于维护分布式系统中的配置信息、命名、提供分布式同步和提供组服务等。它的核心是原子广播和大约一致性模型&#xff0c;这使得它能够…

CCF-GESP五级考级——初等数论,全网最精简的求最大公约数gcd和最小公倍数lcm方法(100%好使)

&#x1f451;一、约数和因数的区别 约数必须在整除的前提下才存在&#xff0c;而因数是从乘积的角度来提出的。如果数与数相乘的积是数&#xff0c;是的因数。 1.约数只能对在整数范围内而言&#xff0c;而因数就不限于整数的范围。 举个栗子&#xff1a;。2和8是16的…

中仕公考:国考往年招录情况对比

2025年国考预计10月中旬启动&#xff0c;11月进行笔试。中仕为大家总结了往年的国考招录情况&#xff0c;希望能给大家一些参考。 2024年计划招录3.96万人。截止到考试结束&#xff0c;共有225.2万人参加了考试&#xff0c;参加考试人数与录用计划数之比约为57:1&#xff0c;2…

CSP-J 2023真题一轮

选择题 阅读题 第1题 第2题 第3题 完善程序 第1题 第2题 答案&#xff1a; 一、单选题 1-5 BDAAC 6-10 BCADA 11-15 ABBAD 二、阅读程序 1&#xff09; 16. √ 17. √ 18. ⅹ 19.A 20.B 2&#xff09; 21. √ 22. ⅹ 23. √ 24. D 25.B 26.D 3&#xff09; 27. √ 28. √ 29…

EasyCVR视频汇聚平台构建远程安防监控:5大亮点解析,助力安防无死角

随着科技的飞速发展&#xff0c;远程安防监控系统已经成为现代社会中不可或缺的一部分&#xff0c;无论是在小区、公共场所还是工业领域&#xff0c;安防监控都发挥着至关重要的作用。而EasyCVR作为一款功能强大的视频监控综合管理平台&#xff0c;其在构建远程安防监控系统方面…

谷歌浏览器下载文件被阻止怎么解除

在工作生活中&#xff0c;我们会使用谷歌浏览器下载各种各样的文件&#xff0c;不过偶尔会遇到文件下载被阻止的情况。为了解决这一问题&#xff0c;本文为大家分享了实用的措施建议&#xff0c;一起来了解一下吧。&#xff08;本文由https://chrome.cmrrs.com/站点的作者进行编…

python爬取豆瓣电影数据

目录 一、背景 二、分析网站 1、ajax请求 三、代码实现 1、导包 2、面向对象实现 3、发送请求 4、解析数据 5、保存数据 6、定义主函数 7、实例化对象运行主函数 8、运行效果 四、以下是全部完整代码 五、报错解决 1、数据库连接报错 2、数据插入报错 一、背景…

136 只出现一次的数字

解题思路&#xff1a; \qquad 这道题目明确要求了时间复杂度为O(N)&#xff0c;空间复杂度为O(1)&#xff0c;不然借助哈希表很容易能够在O(N)的空间复杂度下解决。特殊的要求只能特殊处理&#xff0c;解这道题只能记住异或这种较特殊的运算方式。 \qquad 异或是对二进制数进…

《深入探究 @SpringBootApplication 注解的内部原理》

《深入探究 SpringBootApplication 注解的内部原理》 SpringBootApplication注解涵盖了 Spring Boot 的包扫描原理、自动装配原理等众多重要原理。接下来&#xff0c;我们将对该注解展开深入且详尽的研究。而研究上述原理的关键&#xff0c;在于剖析SpringBootApplication内部…

网上商品订单转手系统bootpf

TOC springboot408网上商品订单转手系统bootpf 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔记本的…

【SpringBoot】SpringBoot框架的整体环境搭建和使用(整合Mybatis,Druid,Junit4,PageHelper,logback等)

目录 1.介绍 1.1 配置文件 1.2 目录结构 2.基于SpringBoot的SpringMVC 4.整合Mybatis 5.整合Druid连接池 6.整合Junit4 7.整合Logback 8.整合PageHelper 9.SpringBoot整合Thymeleaf ​编辑 【附录】springboot的pom.xml 1.介绍 Spring框架的优点是方便解耦、简化开…

openEuler系统安装Visual Studio Code

openEuler系统安装Visual Studio Code 背景安装密钥和存储库更新包缓存并使用dnf安装包Fedora 22及以上版本旧版本使用yum 安装过程截图安装成功看桌面效果 背景 openEuler(openEuler-24.03-LTS)安装了麒麟UKUI桌面但是没有麒麟软件商店想安装Visual Studio Code 安装密钥和…

计算机毕业设计选什么题目好? springboot 大学志愿填报系统

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

东晟时尚服饰文化传承与发展研发中心成立

近期&#xff0c;东晟时尚创新科技&#xff08;北京&#xff09;有限公司宣布成立东晟时尚服饰文化传承与发展研发中心&#xff0c;此举标志着公司在促进中国传统文化与现代时尚产业结合方面迈出了关键步伐。 作为一家在时尚科技推广和设计研发应用服务领域具有战略眼光的企业&…

微信云开发云存储 下载全部文件

一、安装 首先按照这个按照好依赖&#xff0c;打开cmd 安装 | 云开发 CloudBase - 一站式后端云服务 npm i -g cloudbase/cli 安装可能遇到的问题 ‘tcb‘ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。-CSDN博客 二、登录 在cmd输入 tcb login 三、…

导出运营数据Excel报表

文章目录 概要整体架构流程技术细节小结 概要 产品原型 在数据统计页面&#xff0c;有一个数据导出的按钮&#xff0c;点击该按钮时&#xff0c;其实就会下载一个文件。这个文件实际上是一个Excel形式的文件&#xff0c;文件中主要包含最近30日运营相关的数据。表格的形式已经…

C语言(16)——初识单链表

1.链表的概念及结构 概念&#xff1a;链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 结构图&#xff1a; 补充说明&#xff1a; 1、链式机构在逻辑上是连续的&#xff0c;在物理结构上不⼀定连续 2、…

【网络】自定义(应用层)协议——序列化和反序列化

我们接着上一篇&#xff1a;http://t.csdnimg.cn/Xt18d 我们之前写的代码都是在应用层的&#xff0c;而TCP是在应用层下面一层的传输层 1.自定义协议&#xff08;应用层&#xff09; 1.1.应用层和传输层的关系 应用层和传输层的概述 应用层&#xff1a;位于网络协议的最高层…