记一次线上数据库删除百万级数据
1|0背景
不知道有没有读者经历过删除线上数据库记录,反正这事对我来说是挺有压力的。激动的心,颤抖的手,万一删错了数据就麻烦了,影响数量大,领导会批评,还有复盘自己批评,想想就头大。那么就要在删除数据之前做好计划,避免删数据时发生意料之外的事情。记录一次删除线上数据。
业务以半年为一个周期,每一个周期体验参与用户在40w左右。新一期开始后过期体验用户的数据较大,会让数据库增删改查速度变慢,但这一部分数据对业务已经没有帮助了,所以要清理过期体验用户的数据。
一共要清理5张表:
A:数量 36w
B:数量 36w
C:数量 140w
D:数量 36w
E:数量 72w
2|0要求
对于大量数据的查询和删除不能使用一条语句完成,会造成数据库阻塞,特别是删除数据时会锁表或锁行。要减少对线上正常业务的影响,在删除数据的同时不能影响数据库正常增删改查,而且不能让数据库查询等待过长而导致API返回超时。所以查询和删除都需要分批完成。
3|0删除数据底层流程
简单的说明一下在删除数据时MySQL数据底层流程。
MySQL数据库分为两个部分:server层和存储引擎,如下图:
在删除一条记录时,流程分别是:
- 客户端连接到server层
- 分析器对sql语句进行词法分析和语法分析,知道是一条删除语句
- 优化器选择合适的索引去查找待删除的记录
- 执行器调用存储引擎删除所有记录
- 存储引擎将维护的数据内存里的记录标记为已删除
- 存储引擎根据刷盘规则将内存的记录写到磁盘中
以上就是删除一条语句的过程,因为每一个sql语句是一个事务,每一个事务都涉及到加锁,所以在以上的删除流程中,锁的使用是这样的:
- 如果查询待删除记录走的是索引,那么会将所有删除记录行加锁
- 如果查询待删除记录没有走索引,那么将会将整张表都锁起来,直到删除完成
4|0删除实施
针对最多140w的数据,肯定不能一次性删除,否则锁表的时间会让其他业务无法进行,同时要在删除时使用行锁而不是表锁。所以删除分为两步走:
- 使用分块查询,将所有记录的主键查询出来
- 根据主键分批删除,同时每一次删除间隔一定时间,异常捕获不影响删除流程
最多的140w数据耗时在10分钟左右,全程数据库无波动,业务没有影响。
__EOF__

本文作者:goldsunshine
本文链接:https://www.cnblogs.com/goldsunshine/p/16484247.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/goldsunshine/p/16484247.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)