MySQL如何优雅的删除大表实例详解

前言

删除表,大家下意识想到的命令可能是直接使用DROP TABLE "表名",这是初生牛犊的做法,因为当要删除的表达空间到几十G,甚至是几百G的表时候。这样一条命令下去,MySQL可能就直接夯住了,外在表现就是QPS急速下降,客户请求变慢。

解决办法

1.业务低峰时间手动执行删除

这个可能就需要DBA不辞辛劳,大晚上爬起来删表了。

2.先清除数据,最后再删除的方式

譬如1000万条数据,写脚本每次删除20万,睡眠一段时间,继续执行。这样也能做到对用户无感知。

3.对表文件(idb文件)做一个硬链接来加速删除

这个方法利用了linux下硬链接的知识,来进行快速删除,不记得话可以回去翻一下《鸟哥的linux私房菜》

ln data_center_update_log.ibd data_center_update_log.ibd.hdlk

[root@mysql01 sports_center]# ll
总用量 19903792
-rw-r----- 1 mysql mysql  9076 10月 17 13:15 data_center_update_log.frm
-rw-r----- 2 mysql mysql 8447328256 12月 23 11:35 data_center_update_log.ibd
-rw-r----- 2 mysql mysql 8447328256 12月 23 11:35 data_center_update_log.ibd.hdlk

执行上面命令后,我们就多了一个data_center_update_log.ibd.hdlk文件。此操作实际上不会占用磁盘空间,只是增加了一次对磁盘上文件的引用。

当我们删除其中任何一个文件时,都不会影响磁盘上真实的文件,只是将其引用数目减去1。当被引用的数目变为1的时候,再去删除文件,才会真正做IO来删除它。

正是利用这个特点,将由原来mysql来删除大文件的操作,转换为一个简单的操作系统级的文件删除,从而减少了对mysql的影响。

4.登陆mysql,执行drop表操作

很快,200万条数据只用了1秒完成,此操作是在创建硬链接后执行的

mysql> drop tables data_center_update_log;
Query OK, 0 rows affected (1.02 sec)

mysql> exit
Bye

退出来,再次查看数据目录,发现就只剩data_center_update_log.ibd.hdlk硬链接文件了
[root@mysql01 sports_center]# ll
总用量 19903792
-rw-r----- 2 mysql mysql 8447328256 12月 23 11:35 data_center_update_log.ibd.hdlk

5.如何正确删除ibd.hdlk硬链接文件呢

  • 虽然drop table之后,剩下的硬链接文件已经和mysql没有关系了。但如果文件过大,直接用rm命令来删除,也是会造成IO开销飙升,CPU负载过高,进而影响到MySQL。
  • 这里我们用到的方法,可以循环分块删除,慢慢地清理文件,通过一个脚本即可搞定
  • Truncate命令通常用于将文件缩小或扩展到指定的大小。如果文件大于指定的大小,则会丢失额外的数据。如果文件较短,则会对其进行扩展,并且扩展部分的读数为零字节。

5.1 安装truncate命令

[root@mysql01 ~]# cruncate
-bash: cruncate: 未找到命令
通常操作系统会安装truncate命令,该命令在coreutils安装包里面,如果没有安装可以使用下面命令安装

[root@mysql01 ~]# yum provides truncate
coreutils-8.22-24.el7.x86_64 : A set of basic GNU tools commonly used in shell scripts
源  :base
匹配来源:
文件名  :/usr/bin/truncate

可以看到truncate由coreutils安装包提供,下面安装coreutils安装包:

[root@mysql01 ~]# yum install -y coreutils

5.2 truncate常用选项

-c, --no-create --> 不创建任何文件
-o, --io-blocks --> 将大小视为存储块的数量,而不是字节
-r, --reference=RFILE --> 参考指定的文件大小
-s, --size=SIZE --> 按照指定的字节设置文件大小

5.3 truncate_bigfile.sh脚本

原理:使用truncate -s选项可以指定文件大小,通过脚本指定每次文件减少的大小,并sleep睡眠一定时间,从而达到可控的删除文件

附:truncate_bigfile.sh脚本

#! /bin/bash
#

TRUNCATE=/usr/bin/truncate
FILE=$1

if [ x"$1" = x ];then
 echo "Please input filename in"
 exit 1;
else
 SIZE_M=$(du -sm "$1" | awk '{print $1}')

 for i in $(seq "${SIZE_M}" -100 0)
 do
 sleep 1
 echo "${TRUNCATE} -s ${i}M ${FILE}"
 ${TRUNCATE} -s "${i}"M "${FILE}"
 done
fi

if [ $? -eq 0 ];then
    \rm -f "${FILE}"
else
    echo "Please check file"
fi

总结

到此这篇关于MySQL如何优雅的删除大表的文章就介绍到这了,更多相关MySQL优雅删除大表内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Innodb中mysql快速删除2T的大表方法示例

    前言 本文主要给大家介绍了关于Innodb中mysql快速删除2T的大表的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 来,先来看小漫画陶冶一下情操 OK,这里就说了.假设,你有一个表erp,如果你直接进行下面的命令 drop table erp 这个时候所有的mysql的相关进程都会停止,直到drop结束,mysql才会恢复执行.出现这个情况的原因就是因为,在drop table的时候,innodb维护了一个全局锁,drop完毕锁就释放了. 这意味着,如果在白天,访

  • MySQL 删除大表的性能问题解决方案

    微博上讨论MySQL在删除大表engine=innodb(30G+)时,如何减少MySQL hang的时间,现做一下简单总结: 当buffer_pool很大的时候(30G+),由于删除表时,会遍历整个buffer pool来清理数据,会导致MySQL hang住,解决的办法是: 1.当innodb_file_per_table=0的时候,以上不是问题,因为采用共享表空间的时候,该表所占用的空间不会被删除,buffer pool中的相关页不会 被discard. 2.当innodb_file_pe

  • MySQL如何优雅的删除大表实例详解

    前言 删除表,大家下意识想到的命令可能是直接使用DROP TABLE "表名",这是初生牛犊的做法,因为当要删除的表达空间到几十G,甚至是几百G的表时候.这样一条命令下去,MySQL可能就直接夯住了,外在表现就是QPS急速下降,客户请求变慢. 解决办法 1.业务低峰时间手动执行删除 这个可能就需要DBA不辞辛劳,大晚上爬起来删表了. 2.先清除数据,最后再删除的方式 譬如1000万条数据,写脚本每次删除20万,睡眠一段时间,继续执行.这样也能做到对用户无感知. 3.对表文件(idb文件

  • 浅谈MySQL如何优雅的做大表删除

    随着时间的推移或者业务量的增长,数据库空间使用率也不断的呈稳定上升状态,当数据库空间将要达到瓶颈的时候,可能我们才会发现数据库有那么一两张的超级大表!他们堆积了从业务开始到现在的全部数据,但是90%的数据都是没有业务价值的,这时候该如何处理这些大表? 既然是没有价值的数据,我们通常一般会选择直接删除或者归档后删除两种,对于数据删除的操作方式来说又可分为两大类: 通过truncate直接删除表中全部数据 通过delete删除表中满足条件记录 一.Truncate操作 从逻辑意义上来讲,trunca

  • mysql的存储过程、游标 、事务实例详解

    mysql的存储过程.游标 .事务实例详解 下面是自己曾经编写过的mysql数据库存储过程,留作存档,以后用到的时候拿来参考. 其中,涉及到了存储过程.游标(双层循环).事务. [说明]:代码中的注释只针对当时业务而言,无须理会. 代码如下: DELIMITER $$ DROP PROCEDURE IF EXISTS `transferEmailTempData`$$ CREATE PROCEDURE transferEmailTempData(IN jobId VARCHAR(24)) BEG

  • MySQL分类排名和分组TOP N实例详解

    目录 表结构 题目一:获取每个科目下前五成绩排名(允许并列) 分析: 题目二:获取每个科目下最后两名学生的成绩平均值 分析: 题目三:获取每个科目下前五成绩排名(不允许并列) 分析: 总结 表结构 学生表如下: CREATE TABLE `t_student` ( `id` int NOT NULL AUTO_INCREMENT, `t_id` int DEFAULT NULL COMMENT '学科id', `score` int DEFAULT NULL COMMENT '分数', PRIM

  • MySql批量插入优化Sql执行效率实例详解

    MySql批量插入优化Sql执行效率实例详解 itemcontractprice数量1万左右,每条itemcontractprice 插入5条日志. updateInsertSql.AppendFormat("UPDATE itemcontractprice AS p INNER JOIN foreigncurrency AS f ON p.ForeignCurrencyId = f.ContractPriceId SET p.RemainPrice = f.RemainPrice * {0},

  • Java集合删除元素ArrayList实例详解

    Java集合删除元素ArrayList实例详解 AbstractCollection集合类中有一个remove方法,该方法为了适配多种不同的集合,允许删除空的元素,看这部分代码的时候产生了疑问,为什么这里直接用it.remove()就直接删除了? public boolean remove(Object o) { Iterator<E> it = iterator(); if (o==null) { while (it.hasNext()) { if (it.next()==null) { i

  • Linux下使用killall命令终止进程的8大用法实例详解

    Linux 的命令行提供很多命令来杀死进程.比如,你可以向 kill 命传递一个PID来杀死进程:pkill 命令使用一个正则表达式作为输入,所以和该模式匹配的进程都被杀死. 但是还有一个命令叫 killall ,默认情况下,它精确地匹配参数名,然后杀死匹配进程.在这篇文章中,我们将讨论有关这个命令的实际应用. 默认情况下,killall 命令将向一个/组进程发送一个 SIGTERM 信号,但是,也可以通过参数发送一个指定的信号. 下面我们通过例子详细介绍 killall 的 8 大用法. 1.

  • MySQL死锁问题分析及解决方法实例详解

    MySQL死锁问题是很多程序员在项目开发中常遇到的问题,现就MySQL死锁及解决方法详解如下: 1.MySQL常用存储引擎的锁机制 MyISAM和MEMORY采用表级锁(table-level locking) BDB采用页面锁(page-level locking)或表级锁,默认为页面锁 InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁 2.各种锁特点 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低 行级锁:开销大,加锁慢;

  • MySQL数据库查询进阶之多表查询详解

    目录 一.多表查询 1.引出 2.笛卡尔积 3. 笛卡尔积的解决方法 二.多表查询分类 1.等值连接和非等值连接 2.自连接和非自连接 3.内连接和外连接 4.UNION 4.自然连接 5.using连接 三.子查询 1.不相关子查询 2.相关子查询 四.聚合函数 1.聚合函数介绍 1.1 AVG和SUM函数 1.2 MIN和MAX函数 1.3 COUNT函数 2.group by 3.使用having进行分组后的筛选 五.where和having的对比 六.select的执行过程 1.关键字顺

  • C语言实现散列表(哈希Hash表)实例详解

    C语言实现散列表(哈希Hash表) 实例代码: //散列表查找算法(Hash) #include <stdio.h> #include <stdlib.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define SUCCESS 1 #define UNSUCCESS 0 #define HASHSIZE 7 #define NULLKEY -32768 typedef int Status; type

随机推荐