在MySQL中如何有效的删除一个大表?

在MySQL中如何有效的删除一个大表?




Oracle大表的删除:http://blog.itpub.net/26736162/viewspace-2141248/



在DROP TABLE 过程中,所有操作都会被HANG住。
这是因为INNODB会维护一个全局独占锁(在table cache上面),直到DROP TABLE完成才释放。
在我们常用的ext3,ext4,ntfs文件系统,要删除一个大文件(几十G,甚至几百G)还是需要点时间的。
下面我们介绍一个快速DROP table 的方法; 不管多大的表,INNODB 都可以很快返回,表删除完成;
实现:巧用LINK(硬链接)

实测:

root@127.0.0.1 : test 21:38:00> show table status like ‘tt’ \G
*************************** 1. row ***************************
Name: tt
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 151789128
Avg_row_length: 72
Data_length: 11011096576
Max_data_length: 0
Index_length: 5206179840
Data_free: 7340032
Auto_increment: NULL
Create_time: 2011-05-18 14:55:08
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.22 sec)

root@127.0.0.1 : test 21:39:34> drop table tt ;
Query OK, 0 rows affected (25.01 sec)

删除一个11G的表用时25秒左右(硬件不同,时间不同);

下面我们来对另一个更大的表进行删除;
但之前,我们需要对这个表的数据文件做一个硬连接:

root@ # ln stock.ibd stock.id.hdlk
root@ # ls stock.* -l
-rw-rw—- 1 MySQL mysql        9196 Apr 14 23:03 stock.frm
-rw-r–r– 2 mysql mysql 19096666112 Apr 15 09:55 stock.ibd
-rw-r–r– 2 mysql mysql 19096666112 Apr 15 09:55 stock.id.hdlk

你会发现stock.ibd的INODES属性变成了2;

下面我们继续来删表。

root@127.0.0.1 : test 21:44:37> show table status like ‘stock’ \G
*************************** 1. row ***************************
Name: stock
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 49916863
Avg_row_length: 356
Data_length: 17799577600
Max_data_length: 0
Index_length: 1025507328
Data_free: 4194304
Auto_increment: NULL
Create_time: 2011-05-18 14:55:08
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.23 sec)

root@127.0.0.1 : test 21:39:34> drop table stock ;
Query OK, 0 rows affected (0.99 sec)

1秒不到就删除完成; 也就是DROP TABLE不用再HANG这么久了。
但table是删除了,数据文件还在,所以你还需要最后数据文件给删除。

root # ll
total 19096666112
-rw-r–r– 2 mysql mysql 19096666112 Apr 15 09:55 stock.id.hdlk
root # rm stock.id.hdlk
虽然DROP TABLE 多绕了几步。(如果你有一个比较可靠的自运行程序(自动为大表建立硬链接,并会自动删除过期的硬链接文件),就会显得不那么繁琐。)
这样做能大大减少MYSQL HANG住的时间; 相信还是值得的。

至于原理: 就是利用OS HARD LINK的原理,
当多个文件名同时指向同一个INODE时,这个INODE的引用数N>1, 删除其中任何一个文件名都会很快.
因为其直接的物理文件块没有被删除.只是删除了一个指针而已;
当INODE的引用数N=1时, 删除文件需要去把这个文件相关的所有数据块清除,所以会比较耗时;




【问题隐患】

    由于业务需求不断变化,可能在DB中存在超大表占用空间或影响性能;对这些表的处理操作,容易造成MySQL性能急剧下降,IO性能占用严重等。先前有在生产库drop table造成服务不可用;rm 大文件造成io跑满,引发应用容灾;对大表的操作越轻柔越好。

    【解决办法】

    1.通过硬链接减少mysql DDL时间,加快锁释放

    2.通过truncate分段删除文件,避免IO hang

    【生产案例】

    某对mysql主备,主库写入较大时发现空间不足,需要紧急清理废弃大表,但不能影响应用访问响应:

    $ll /u01/mysql/data/test/tmp_large.ibd

    -rw-r-– 1 mysql dba 289591525376 Mar 30  2012 tmp_large.ibd

    270GB的大表删除变更过程如下:

    #(备库先做灰度)

    ln tmp_large.ibd /u01/bak/tmp_tbl.ibd  #建立硬链接

    -rw-r-– 2 mysql dba 289591525376 Mar 30  2012 tmp_large.ibd

    set session sql_log_bin=0;

    #不计入bin log节省性能,并且防止主备不一致

    desc test.tmp_large;

    drop table test.tmp_large;

    Query OK, 0 rows affected (10.46 sec)  mysql -uroot -e “start slave;”

    cd /u01/bak;screen -S weixi_drop_table  for i in `seq 270 -1 1 ` ;

    do sleep 2;truncate -s ${i}G tmp_tbl.ibd;done

    rm -rf tmp_tbl.ibd

    【性能比较】

    中间ctrl-C一次,可以看到truncate前后io的对比情况,基本上影响不大

    文件大小也成功更新

    【工具介绍】

    truncate – shrink or extend the size of a file to the specified size

    #来自coreutils工具集

    wget ftp.gnu.org/gnu/coreutils/coreutils-8.9.tar.gz

    tar -zxvf coreutils-8.9.tar.gz

    cd coreutils-8.9  ./configure

    make

    sudo cp src/truncate /usr/bin/



About Me


.............................................................................................................................................

● 本文整理自网络

● 本文在itpub(http://blog.itpub.net/26736162/abstract/1/)、博客园(http://www.cnblogs.com/lhrbest)和个人微信公众号(xiaomaimiaolhr)上有同步更新

● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/

● 本文博客园地址:http://www.cnblogs.com/lhrbest

● 本文pdf版、个人简介及小麦苗云盘地址:http://blog.itpub.net/26736162/viewspace-1624453/

● 数据库笔试面试题库及解答:http://blog.itpub.net/26736162/viewspace-2134706/

● DBA宝典今日头条号地址:http://www.toutiao.com/c/user/6401772890/#mid=1564638659405826

.............................................................................................................................................

● QQ群号:230161599(满)、618766405

● 微信群:可加我微信,我拉大家进群,非诚勿扰

● 联系我请加QQ好友(646634621),注明添加缘由

● 于 2017-08-01 09:00 ~ 2017-08-31 22:00 在魔都完成

● 文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解

● 版权所有,欢迎分享本文,转载请保留出处

.............................................................................................................................................

● 小麦苗的微店:https://weidian.com/s/793741433?wfr=c&ifr=shopdetail

● 小麦苗出版的数据库类丛书:http://blog.itpub.net/26736162/viewspace-2142121/

.............................................................................................................................................

使用微信客户端扫描下面的二维码来关注小麦苗的微信公众号(xiaomaimiaolhr)及QQ群(DBA宝典),学习最实用的数据库技术。

   小麦苗的微信公众号      小麦苗的DBA宝典QQ群1     小麦苗的DBA宝典QQ群2        小麦苗的微店

.............................................................................................................................................

时间: 2024-11-05 16:28:34

在MySQL中如何有效的删除一个大表?的相关文章

如何在azure网站中快速删除一个大文件夹

问题描述 如何在azure网站中快速删除一个大文件夹 我在Azure网站中部署了个我的website的应用,我现在想删去里面一个文件夹,大小大概有3G,我尝试使用ftp去做,但是速度太慢了,有们有什么快速的方法. 解决方案 Hi, 我们可以通过kudu这个工具快速的删除一个文件夹,我们首先去Azure网站的仪表盘下载发布配置文件,具体如下图: 打开配置文件找出用户名密码,然后我们打开IE输入https://***.scm.chinacloudsites.cn/, ***是你的网站名称,输入上面记

mysql中alter数据表中增加、删除字段与表名修改例子

 alter是非常强大的一个功能我们可以利用alter来修改数据表表名字体名及一些其它的操作了,下面一起来看看mysql中alter数据表中增加.删除字段与表名修改的一个例子.     修改删除mysql数据库中的数据内容: [root@hk ~]# /usr/local/mysql/bin/mysql -uroot -p'admin' #进入mysql mysql> create database gbk default character set gbk collate gbk_chines

数据-mysql中的事务处理,请大神指教

问题描述 mysql中的事务处理,请大神指教 假如我已经用了START TRANSACTION开启事务后,在ROLLBACK之前,我删除了表中的数据,然后SELECT,表中的数据已经空的了,当执行ROLLBACK后,数据又回来了,那么,DELETE后到ROLLBACK前,数据是存在缓存里面的吗? 解决方案 是的,否则无法回滚的 解决方案二: MySQL事务处理c++与mysql中的事务处理mysql事务处理

为什么 MySQL 中 GROUP_CONCAT 函数返回 BLOB 大对象类型?(Why GROUP_CONCAT returns BLOB?)

为什么 MySQL 中 GROUP_CONCAT 函数返回 BLOB 大对象类型?(Why GROUP_CONCAT returns BLOB?) 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作.

mysql中可以相关删除吗?或者替代方案是什么

问题描述 mysql中可以相关删除吗?或者替代方案是什么 解决方案 级联删除?解决方案二:可以ALTER TABLE `test1`ADD CONSTRAINT `FK_test1_t1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`) ON UPDATE CASCADE ON DELETE CASCADE;ON DELETE CASCADE解决方案三:一般会用事务来做,比如你删一个主表的一条记录,同时还想把与这个表有关系的表的数据也删掉的话 可以将这2个删除

mysql在线无性能影响删除7G大表

mysql在线无性能影响删除7G大表 如何在mysql数据库里删除7G(或更大)大表,使其又不影响服务器的io,导致性能下降影响业务.先不说其是mysql表,就是普通文件,如果直接rm删除,也会使服务器的io性能急剧下降:换个思路如果用化整为零的方式,分多次大大文件一点一点删除,就可以避免因删除文件占用太多服务器io资源 例子: www.bitsCN.com 版本: mysql> select version(); +------------+ | version()  | +---------

Ext中如何动态生成一个form表单

问题描述 Ext中如何动态生成一个form表单,主要是表单里的item配置是会变的,根据数据库的数据会变.怎样动态生成这个表单呢. 问题补充:lizhi92574 写道 解决方案 var item, items = form.getForm().items;while ((item = items.last())) { //删除组件form.getForm().remove(item);form.remove(item);}form.add();//添加组件form.doLayout();解决方

ubuntu-mysqldump出的数据库sql文件在另一机器的mysql中source导入结果不一致,表丢失

问题描述 mysqldump出的数据库sql文件在另一机器的mysql中source导入结果不一致,表丢失 求指导.用mysqldump导出一张有128张表的数据库sql文件,在另一台机器的mysql中source导入,只剩下84张表.重复多次,也是同样的表丢失.请问这是什么原因啊?系统都是linux ubuntu14.04,mysql5.5 解决方案 没碰到过这样的问题,按理应该source以后是一致的.数据库是不是有什么配置问题 解决方案二: 还有一个现象是,我迁移到windows下的mys

MySQL中使用SQL语句查看某个表的编码方法_Mysql

MySQL中,如何使用SQL语句来查看某个表的编码呢?我们使用show create table 这一SQL语句来解决这个问题. show create table可以查看创建这个表的SQL语句脚本,它的基本语法是: show create table <表名>; 我们用它看看test表的create脚本: mysql> show create table test; +-------+--------------------------------------------- -----