夜间数据库IO负载飙升?MySQL批量删除操作引发的问题排查

news/2024/12/21 23:03:18/

目录

问题现象

问题分析

修改建议

总结


问题现象

近日,某用户反馈他们的MySQL数据库实例在凌晨时段会频繁出现IO负载急剧上升的情况,这种状态会持续一段时间,随后自行恢复正常。为了查明原因,该用户通过DBdoctor工具收集了相关的监控数据和审计日志进行分析。以下是他们收集到的关键数据:AAS监控数据和审计日志分析结果。

图片

图片

问题分析

通过审计日分析我们可以看到,在IO突增时间的时间段内, delete from order_info where id=? 这个SQL被执行超过了100万+次,这种短时间内的大量删除操作可能会对MySQL的IO性能造成影响。用户将分析数据提供给开发同学,开发团队通过追踪这个SQL语句,发现了一个新近添加的定时任务,该任务设置在每天凌晨运行,目的是清除历史数据。该代码如下:

public void cleanExpireData(long startTime, long endTime) {        List<OrderInfo> orderList = orderInfoDao.findByTime(startTime, endTime);        if (CollectionUtils.isEmpty(orderList)) {            log.info("no data found between {} and {}", startTime, endTime);            return;        }        for (OrderInfo orderInfo : orderList) {            orderInfoDao.deleteById(orderInfo.getId());        }        log.info("clean all data success");}

通过分析这个 cleanExpireData 的目的是清理在指定时间范围内的过期数据。它通过以下步骤实现:

  1. 调用orderInfoDao.findByTime(startTime,endTime) 获取在 startTime 和 endTime 之间的所有数据的列表。

  2. 如果找到数据,则遍历每个对象ID,并调用orderInfoDao.deleteById(id) 方法逐个删除。

那原因找到了,这是因为该定时任务在批量删除数据时先进行了查询操作,再进行一条一条数据删除而导致的数据库IO异常,同时该逻辑还可能会产生OOM,具体分析如下:

1.潜在OOM风险:当查询时间范围内若数据量异常过大,一次查询出来,可能会占用大量内存,造成程序OOM。

2.逐个删除记录效率低下

  • 每次删除一条记录时,都会发起一次单独的数据库操作(deleteById)。如果 allIds 列表中有很多条数据,逐条删除会导致大量的数据库请求,从而导致性能降低。

3.频繁大量进行MySQL删除操作会增加系统IO

  • 每次删除操作都会导致 MySQL 更新数据文件和索引文件,以标记删除的记录。这会触发大量的磁盘写入操作,特别是如果表中有大量索引需要更新。

  • 对于 InnoDB 引擎,删除操作还会产生大量的 Undo Log 和 Redo Log 写操作,用于维护事务一致性和崩溃恢复。

  • 如果 MySQL 开启了 二进制日志(binlog),每个删除操作都会记录到 binlog 中,以便进行事务恢复和主从复制。删除大量数据会导致 MySQL 频繁地将这些操作写入到 binlog 中,增加磁盘的 I/O 压力

  • 删除大量数据后,表会产生空间碎片,尤其是在 InnoDB 引擎中,删除操作并不会立即释放磁盘空间,数据页中的记录会被标记为“已删除”,这可能导致表空间利用率降低。后续的操作(如INSERTUPDATE)会导致表空间整理,进一步增加 I/O 负载

修改建议

  1. 避免大数据查询:简单的删除操作,可根据过滤条件直接从数据库中删除,无需查询出来再删除。

  2. 批量删除:根据指定时间范围内直接删除,同时限制批量删除个数,防止数据量过大,对数据库造成负载。

修改后代码如下:

public void cleanExpireData(long startTime, long endTime) {    long effectNum = 1;    long totalDeleted = 0;  // 记录删除的总数    while (effectNum > 0) {        effectNum = orderInfoDao.deleteByTimeAndLimit(startTime, endTime, 10000);        totalDeleted += effectNum;  // 累积删除的数量    }    log.info("Successfully cleaned {} records between {} and {}", totalDeleted, startTime, endTime);}
##SQL如下:delete from orderInfo where start_time > #{startTime} and end_time < #{endTime} limit #{num}

      修改后的代码实现了直接删除满足条件的数据,避免了先查询再删除的步骤。为了提高效率并防止一次性删除大量数据,我们采用了分批删除的策略,每次删除不超过10000条记录。这样的改进使得代码更加简洁,执行速度也得到了显著提升。代码修改点如下:

1. 避免一次性处理大量数据,采取批量操作

在处理大数据量的操作时(如删除、更新等),避免一次性加载或操作过多数据,防止耗尽内存及造成的数据库性能问题。分批次处理(如使用 LIMIT)可以有效降低系统压力,同时避免长时间的锁定资源,保持系统的稳定性。

2. 循环操作和停止条件

在执行分批操作时,我们引入了循环机制,并设定了明确的停止条件,以确保所有数据都能被逐一处理。通过限制每次操作处理的数据量,并让循环持续执行直到没有更多数据需要处理,我们能够有效地避免数据遗漏,确保数据处理的完整性和准确性。

3. 记录并跟踪处理结果

通过记录每次操作的结果(如删除的条数)来追踪进度,能够帮助我们准确了解批量操作的效果。此外,正确处理并累积删除的记录总数,有助于调试、日志输出和分析。

4. 灵活选择批量操作的数量

设定合适的批量操作数量(如每次删除 10,000 条),根据数据库的规模和性能动态调整。过大可能导致数据库负载过高,过小则会使效率低下。

总结

     在执行数据库定期清理任务时,建议采用分批删除策略,以减少对数据库性能的影响。首先,根据设定的条件筛选出待删除的数据。然后,为了避免一次性删除大量数据导致数据库压力过大,可以实施分批处理。此外,如果数据库频繁出现性能问题,应检查是否有定时任务在特定时间点执行。利用DBdoctor审计日志分析工具,可以帮助我们迅速诊断并定位问题源头。

**************************************************************************************************************

DBdoctor-1分钟定位数据库性能问题DBdoctor是一款企业级数据库监控、巡检、性能诊断、SQL审核与优化平台,利用eBPF透视数据库内核,可一分钟定位数据库性能问题,实现根因诊断,并给出优化建议。icon-default.png?t=O83Ahttps://www.dbdoctor.cn/?utm=4cf70f49547b4b45864ac76d1da334bf


http://www.ppmy.cn/news/1536949.html

相关文章

ECCV`24 | 新加坡国立华为提出Vista3D: 实现快速且多视角一致的3D生成

文章链接&#xff1a;https://arxiv.org/pdf/2409.12193 gitbub链接&#xff1a;https://github.com/florinshen/Vista3D 亮点直击 提出了Vista3D&#xff0c;一个用于揭示单张图像3D darkside 的框架&#xff0c;能够高效地利用2D先验生成多样的3D物体。开发了一种从高斯投影到…

python不用ide也能进行调试

import pdb pdb.set_trace()import pdb 和 pdb.set_trace() 是 Python 中用于调试代码的工具。以下是它们的具体含义和用法&#xff1a; import pdb pdb 是 Python 的内置调试器模块&#xff0c;允许开发者在运行时进行代码调试。 通过 import pdb 语句&#xff0c;你可以引入…

深入解析 GPT 系列模型:核心原理、应用与未来发展

1. 引言 1.1 GPT 系列模型概述 GPT&#xff08;Generative Pre-trained Transformer&#xff09;是由 OpenAI 开发的一类生成式预训练语言模型。基于 Transformer 架构&#xff0c;GPT 模型具备强大的自然语言处理能力&#xff0c;能够通过自回归方式生成文本。自首次推出以来…

基于Android11简单分析audio_policy_configuration.xml

开篇先贴上一个高通的例子&#xff0c;后续基于此文件做具体分析。 1 <?xml version"1.0" encoding"UTF-8" standalone"yes"?> 2 <!-- Copyright (c) 2016-2019, The Linux Foundation. All rights reserved 3 Not a Contribut…

JavaScript 访问者模式:打造高扩展性的对象结构

一. 前言 在面向对象编程中&#xff0c;访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为设计模式&#xff0c;它允许我们向现有的类结构添加新的操作&#xff0c;而无需修改这些类。这对于需要对类层次结构中的元素进行复杂算法处理的场景非常有用。 本文将详细…

第五十九周周报 IAGNN

文章目录 week 59 IAGNN摘要Abstract一、大数据相关1. 磁盘扩容以及数据恢复2. 单机hbase 二、文献阅读1. 题目2. Abstract3. 网络结构3.1 问题定义3.2 IAGNN 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程4.4 实验结果 5. 结论参考文献 week 59 IAGNN 摘要 本周阅读了…

多模态简单了解

多模态 1.文本编码2. ViT图像编码器2.1图像矩阵self-attention计算&#xff1a; 3.Transformer多模态3.1CLIP 图文交互3.2 对比学习训练3.3 flamingo 图文交互3.4 LLava 图文交互 1.文本编码 简介&#xff1a; 即通过embedding将字符向量化&#xff0c;进入模型即可。 2. ViT…

selenium-Alert类用于操作提示框/确认弹框(4)

之前文章我们提到&#xff0c;在webdriver.WebDriver类有一个switch_to方法&#xff0c;通过switch_to.alert()可以返回Alert对象&#xff0c;而Alert对象主要用于网页中弹出的提示框/确认框/文本输入框的确认或者取消等动作。 Alert介绍 当在页面定位到提示框/确认框/文本录入…