当删除的数据量过大时,可能会导致实例卡顿、HA切换、实例抖动或复制延迟等问题。本文将介绍解决这些问题的方法。
在数据库运维中,删除表中部分数据、清空表或删除整个表是常见的操作。对于小规模的数据集,这些操作对数据库实例的影响可以忽略。然而,当涉及数百万乃至上亿行记录,或者数据文件达到几百GB甚至数TB时,这类操作可能会引发如下严重问题。 问题1:Binlog提交阶段,在单个大事务中删除大量数据时,生成的临时Binlog文件可能达到数十GB甚至数百GB。提交这些Binlog时会阻塞其他写事务,导致短暂卡顿或长时间延迟,严重时会因HA探测超时引发主备切换。 问题2:AHI清理阶段,InnoDB需要遍历Buffer Pool清理相关AHI记录,此过程需持有全局锁 问题3:文件删除阶段,大表文件的删除可能导致实例瞬间及后续一段时间内IO资源被完全占用,影响正常请求的处理。 问题4:文件删除阶段,InnoDB会遍历Buffer Pool以清理该表的相关页面。若buffer_pool_size非常大,清理过程将耗时较长,会长时间独占单个Buffer Pool的Mutex,阻碍其他事务正常读写页面,进而引起实例性能波动。 参数配置 说明 支持版本 binlog_cache_free_flush = ON 解决了问题1:大Binlog文件写入阻塞的问题,详情请参见AliSQL自研功能大事务提交优化。 MySQL 8.4 MySQL 8.0:20240731或以上 MySQL 5.7:20240731或以上 innodb_rds_drop_ahi_ahead = ON 解决了问题2:清理AHI的问题,AliSQL自研功能。 MySQL 8.4 MySQL 8.0:20240731或以上 MySQL 5.7:20240731或以上 innodb_data_file_purge = ON innodb_data_file_purge_interval=100 innodb_data_file_purge_max_size=512 解决问题3:IO资源被完全占用问题,详情请参见AliSQL自研功能Purge Large File Asynchronously 重要 建议根据最大IOPS的50%来调整interval和max_size参数。 版本不限 innodb_rds_faster_ddl = ON 解决了问题4:清理Buffer Pool导致实例抖动的问题,详情请参见AliSQL自研功能Faster DDL。 MySQL官方在8.0.23解决了此问题,详情请参见MySQL官方说明(WL#14100: InnoDB: Faster truncate/drop table space)。 MySQL 8.4 MySQL 8.0:20200630或以上 MySQL 5.7:20200630或以上 MySQL 5.6:20200630或以上 说明 为防止误删,可启用AliSQL自研的Recycle Bin功能。该功能会暂时将删除的表移至回收站,并允许设置保留时间,便于数据恢复。 分批操作,建议单次删除的数据量不超过一万行,不要一次性删除大量数据。 MySQL 5.7版本推荐使用 未采用 说明 在MySQL 5.7版本中,DDL操作不具备原子性,实例崩溃可能导致文件残留。 MySQL 8.0、8.4版本推荐使用 MySQL 8.0增加了 使用 说明 使用 直接使用DROP。 问题描述
实例卡顿或HA切换
dict_sys->mutex,耗时较长。详情请参见MySQL官方说明(MySQL Bugs: #91977: Dropping Large Table Causes Semaphore Waits; No Other Work Possible)。实例抖动
解决方案
参数调整
删除数据操作
删除部分数据
删除所有数据
RENAME + DROP操作TRUNCATE是因为其在5.7中通过清空原表空间实现,而非重建新表。# 重建一张相同的表CREATE TABLE t1_new LIKE t1;
# 检查重建表的表定义是否符合预期SHOW CREATE TABLE t1_new;
# 新表和老表交换
RENAME TABLE t1 TO t1_bak, t1_new TO t1;
# 删除原表DROP TABLE t1_bak;
# 检查表空间文件清理进展SELECT * FROM information_schema.innodb_purge_files;
RENAME过程可能触发重命名文件失败导致实例崩溃问题,详情请参见MySQL官方说明(bug#108087 InnoDB:crash because of failure to rename file in DDL),此问题已在AliSQL 5.7 20220731及更高版本中修复。RENAME + DROP或TRUNCATE操作RENAME过程可能触发重命名文件失败导致实例崩溃问题,详情请参见MySQL官方说明(bug#108087 InnoDB:crash because of failure to rename file in DDL),此问题已在AliSQL 5.7 20220731及更高版本中修复。lock TABLE,可以选择是否执行,具体参考8.0.13新增的能力8.0 rename table。RENAME + DROP避免了TRUNCATE过程中潜在的卡顿情况。RENAME + DROP参考如下SQL:# 重建一张相同的表CREATE TABLE t1_new LIKE t1;
# 检查重建表的表定义是否符合预期SHOW CREATE TABLE t1_new;
# 提前锁定新表和老表
lock TABLE t1 write, t1_new write;
# 新表和老表交换
RENAME TABLE t1 TO t1_bak, t1_new TO t1;
# 释放表锁
unlock TABLE;
# 删除原表DROP TABLE t1_bak;
# 检查表空间文件清理进展SELECT * FROM information_schema.innodb_purge_files;
TRUNCATE,参考如下SQL:# truncate表TRUNCATE TABLE t1;
# 检查表空间文件清理进展SELECT * FROM information_schema.innodb_purge_files;
删除大表
# 删除表DROP TABLE t1;
# 检查表空间文件清理进展SELECT * FROM information_schema.innodb_purge_files;