大家在日常运维数据库过程当中经常会遇到数据删除的情况,如果生产环境数百万条数据中,删除其中一部分数据,应该如何不影响生产环境使用的情况下进行数据删除呢,这里给大家分享一个比较简单且实用的删除方式,避免一次性删除造成数据库直接卡死,从而影响正常生产使用。
一、案例介绍
首先给大家分享一个这样一个真实的业务场景,基于myhsql数据库搭建的仓储系统有一张出入库库存的数据表,目前系统已经运行了五六年了,数据量达到了五百多万。客户反馈现场进行出入库的时候非常慢,有的时候需要一分钟甚至更久。客户提出需要优化一下现场人员出入库的速度。这边首先想到的一个比较直接有效的方案就行根据年份删除历史数据,并进行历史数据的备份,以便后续正常查询使用。如何在不影响生产环境使用的情况下进入平稳删除呢。这里给大家分享一个方案,分批p平稳的进行删除呢,今天给大家分享一种比较简单操作,对实际生产使用影响较小的一种解决方式。
二、实战方案
实现思路:首先创建一个存储过程:使用了REPEAT循环来不断执行删除操作,直到库存日志表表中没有数据为止。
在每次循环中,这里使用DELETE语句结合LIMIT子句来删除每次的数据,并在每次循环后提交事务并开启新的事务。
当库存日志表中没有数据时,循环结束,并提交最后一个事务。也表示数据已经完全删除。
注意:根据实际的业务需要指定每次循环需要删除的数据个数,这里指定的为每次删除2000条数据。
具体的存储过程SQL如下:
代码语言:javascript复制DELIMITER //
CREATE PROCEDURE batch_delete_stocklog()
BEGIN
DECLARE rows_affected INT;
START TRANSACTION;
REPEAT
DELETE FROM t_stock_log where year(ctearDate)<=2022 ORDER BY id LIMIT 2000;
COMMIT; -- 提交每次删除的数据
START TRANSACTION; -- 开启新的事务
SELECT COUNT(*) INTO rows_affected FROM t_stock_log where year(ctearDate)<=2022;
UNTIL rows_affected = 0 END REPEAT;
COMMIT; -- 提交最后一个事务
END//
DELIMITER ;
然后执行存储过程
代码语言:javascript复制CALL batch_delete__stocklog();
说明:因为删除的数据量比较大有200w左右,执行时间需要和数据库本身的性能、服务器性能有关,需要耐心等待。执行完成。我这边测试五百万条数据执行了50多分钟。
三、总结
以上是使用分批删除的方式实现百万级数据删除而不影响生产环境使用的一种直接有效方式。大家如果有更好的方式欢迎补充。