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