mysql如何优雅删除大表? 看这篇就够了

迭代珊瑚
• 阅读 1234

MySQL大表删除

有次线上用drop table xxx删除200G的大表,导致MySQL连接数暴涨,业务出现大量5XX,“喜提”一个事故报告。看来还是忽略了一行命令背后产生的“蝴蝶效应”,现在让我们一起来详细扒一扒drop table背后的原理,以及怎么优雅的删除MySQL大表。

原理

MySQL的drop命令主要干了两件事情:

  • 清理buffer pool数据块页面;
  • 删除对应磁盘数据文件ibd;

drop table时,innodb引擎会清理该表每个buffer pool实例中对应数据块页面。这里的清除操作并不是真正的flush,而是将涉及到的页面从flush队列中去除。在去除过程中,删除进程会持有每个buffer pool的全局锁,然后搜索这个buffer pool里对应的页面以便从flush list中删除。如果在buffer pool中需要被搜索并删除的页面过多,遍历时间就会增大,就会导致其他事务操作被阻塞,严重时会导致数据库锁住。

具体过程如下图:

mysql如何优雅删除大表? 看这篇就够了

在删除数据文件时,如果数据文件过大,删除过程中会产生大量的IO,造成磁盘IO飚升,CPU负载过高。

优雅删除大表

如果线上需要删除100G以上的大表,建议按照下面的步骤进行:

  • rename table: 避免删错了表导致业务受影响,先rename下如果有问题可以很快改回来;需要确保rename的表没有事务在运行,否则会阻塞;

    rename table xxx to xxx;
  • 表做硬链接:避免产生高IO,影响数据库性能;当有多个文件名同时指向同一个inode时,删除其中任何一个文件名都很快,因为其直接的物理文件块没有被删除,只是删除了一个指针而已;

    ln xxx.ibd  xxx.ibd.bak
  • drop table: 在业务低峰期执行;

    drop table xxx;
  • 删除物理文件:100G文件,每秒删除1G内容,暂停1s,直到最后文件只剩下1G,删除文件。可以在业务低峰期执行。

    $  for i in `seq 100 -1 1 ` ;   do sleep 1;  truncate  -s  ${i}G  xxx.ibd.bak; done 
    $  rm  -f  table_test.ibd.bak

通过上面步骤,曾在线上删除500G的大表做到了数据库各项性能指标很平稳,业务无感知。

本文由mdnice多平台发布

点赞
收藏
评论区
推荐文章
九路 九路
4年前
面试官:Mysql 中主库跑太快,从库追不上怎么整?
写这篇文章是因为之前有一次删库操作,需要进行批量删除数据,当时没有控制好删除速度,导致产生了主从延迟,出现了一点小事故。今天我们就来看看为什么会产生主从延迟以及主从延迟如何处理等相关问题。坐好了,准备发车!(https://imghelloworld.osscnbeijing.aliyuncs.com/4ed72bf8b1fc67
Wesley13 Wesley13
3年前
mysql主从数据对比工具简介
1Checksum1.1checksum原理checksumtable的原理是对表中的数据进行一行一行的较验和计算,在执行checksum命令时,表会被加一个读锁(readlock),因此对于大表,这是一个很耗时的过程。读锁:又叫S锁/共享锁;当MySQL
Wesley13 Wesley13
3年前
MySQL 8.0 hash join有重大缺陷?
我并不这么看。友情提醒:本文建议在PC端阅读。徐春阳老师发文爆MySQL8.0hashjoin有重大缺陷。文章核心观点如下:多表(比如3个个表)join时,只会简单的把表数据量小的放在前面作为驱动表,大表放在最后面,从而导致可能产生极大结果集的笛卡尔积,甚至耗尽CPU和磁盘空间。就此现象,我也做了个测试。1\.
Wesley13 Wesley13
3年前
MySQL数据库优化技巧
MySQL优化三大方向①优化MySQL所在服务器内核(此优化一般由运维人员完成)。②对MySQL配置参数进行优化(my.cnf)此优化需要进行压力测试来进行参数调整。③对SQL语句以及表优化。MySQL参数优化1:MySQL默认的最大连接数为100,可以在mysql客户端使用以下命令查看mysql
Stella981 Stella981
3年前
Innodb中mysql如何快速删除2T的大表
这个时候所有的mysql的相关进程都会停止,直到drop结束,mysql才会恢复执行。出现这个情况的原因就是因为,在droptable的时候,innodb维护了一个全局锁,drop完毕锁就释放了。这意味着,如果在白天,访问量非常大的时候,如果你在不做任何处理措施的情况下,执行了删大表的命令,整个mysql就挂在那了,在删表期间,QPS会严重下滑,然后产
Wesley13 Wesley13
3年前
Oracle:如果表存在
我正在为Oracle数据库编写一些迁移脚本,并且希望Oracle有类似MySQL的IFEXISTS结构。具体来说,每当我想在MySQL中删除表时,我都会这样做DROPTABLEIFEXISTStable_name;这样,如果表不存在,DROP不会产生错误,脚本可以继续。Oracle是否有类似的机制?
Wesley13 Wesley13
3年前
mysql自增id获取
mysql自增id获取使用max函数:selectmax(id)fromtablename 优点:使用方便快捷。缺点:获取的不是真正的自增id,是表中最大的Id,如果有删除数据的话,那么该值和自增id相差比较大。如果有连表数据,有可能导致数据错乱。使用LAST\_INSERT\_ID
Wesley13 Wesley13
3年前
ThinkPHP Mysql表结构修改类
<?php/\ \  mysql表结构处理类 \  创建数据表,增加,编辑,删除表中字段 \ \/classMysqlManage{  /\   \创建数据库,并且主键是aid   \table要查询的表名   \/  functionc
Stella981 Stella981
3年前
Python批量删除mysql中千万级大量数据
场景描述线上mysql数据库里面有张表保存有每天的统计结果,每天有1千多万条,这是我们意想不到的,统计结果咋有这么多。运维找过来,磁盘占了200G,最后问了运营,可以只保留最近3天的,前面的数据,只能删了。删,怎么删?因为这是线上数据库,里面存放有很多其它数据表,如果直接删除这张表的数据,肯定不行,可能会对其它表有影响。尝试每次只删除
Wesley13 Wesley13
3年前
mysql常用命令
mysql常用命令——删除主键,添加新主键【适用于以前主键不是id的场景】altertable表名change现在主键名现在主键名int(11);altertable表名dropprimarykey;altertable表名addCOLUMN新主键名INT(11)NOTNUL
Wesley13 Wesley13
3年前
MySQL 处理重复数据
有些MySQL数据表中可能存在重复的记录,有些情况我们允许重复数据的存在,但有时候我们也需要删除这些重复的数据。本章节我们将为大家介绍如何防止数据表出现重复数据及如何删除数据表中的重复数据。防止表中出现重复数据你可以在MySQL数据表中设置指定的字段为PRIMARYKEY(主键)或者UNIQUE(唯一)索引来保证数据的唯一性