在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/



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

这篇文章主要给大家介绍了关于Innodb中mysql快速删除2T的大表的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一

前言

本文主要给大家介绍了关于Innodb中mysql快速删除2T的大表的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧

来,先来看小漫画陶冶一下情操

OK,这里就说了。假设,你有一个表erp,如果你直接进行下面的命令


drop table erp

这个时候所有的mysql的相关进程都会停止,直到drop结束,mysql才会恢复执行。出现这个情况的原因就是因为,在drop table的时候,innodb维护了一个全局锁,drop完毕锁就释放了。

这意味着,如果在白天,访问量非常大的时候,如果你在不做任何处理措施的情况下,执行了删大表的命令,整个mysql就挂在那了,在删表期间,QPS会严重下滑,然后产品经理就来找你喝茶了。所以才有了漫画中的一幕,你可以在晚上十二点,夜深人静的时候再删。

当然,有的人不服,可能会说:"你可以写一个删除表的存储过程,在晚上没啥访问量的时候运行一次就行。"
我内心一惊,细想一下,只能说:"大家还是别抬杠了,还是听我说一下业内通用做法。"

一个假设

先说明一下,在这里有一个前提,mysql开启了独立表空间,MySQL5.6.7之后默认开启。

也就是在my.cnf中,有这么一条配置(这些是属于mysql优化的知识,后期给大家介绍)


innodb_file_per_table = 1

查看表空间状态,用下面的命令


mysql> show variables like '%per_table';
+-----------------------+-------+
| Variable_name  | Value |
+-----------------------+-------+
| innodb_file_per_table | OFF |
+-----------------------+-------+

如果innodb_file_per_table的value值为OFF,代表采用的是共享表空间。

如果innodb_file_per_table的value值为ON ,代表采用的是独立表空间。

于是,大家要问我,独立表空间和共享表空间的区别?

共享表空间:某一个数据库的所有的表数据,索引文件全部放在一个文件中,默认这个共享表空间的文件路径在data目录下。 默认的文件名为:ibdata1(此文件,可以扩展成多个)。注意,在这种方式下,运维超级不方便。你看,所有数据都在一个文件里,要对单表维护,十分不方便。另外,你在做delete操作的时候,文件内会留下很多间隙,ibdata1文件不会自动收缩。换句话说,使用共享表空间来存储数据,会遭遇drop table之后,空间无法释放的问题。

独立表空间:每一个表都以独立方式来部署,每个表都有一个.frm表描述文件,还有一个.ibd文件。

.frm文件:保存了每个表的元数据,包括表结构的定义等,该文件与数据库引擎无关。

.ibd文件:保存了每个表的数据和索引的文件。

注意,在这种方式下,每个表都有自已独立的表空间,这样运维起来方便,可以实现单表在不同数据库之间的移动。另外,在执行drop table操作的时候,是可以自动回收表空间。在执行delete操作后,可以通过alter table TableName engine=innodb可以整理碎片,回收部分表空间。

ps: my.cnf中的datadir就是用来设置数据存储目录

好了,上面巴拉巴拉了一大堆,我只想说一个事情:

在绝大部分情况下,运维一定会为mysql选择独立表空间的存储方式,因为采用独立表空间的方式,从性能优化和运维难易角度来说,实在强太多。

所以,我在一开始所提到的前提,mysql需要开启独立表空间。这个假设,百分九十的情况下是成立的。如果真的遇到了,你们公司的mysql采用的是共享表空间的情况,请你和你们家的运维谈谈心,问问为啥用共享表空间。

正确姿势

假设,我们有datadir = /data/mysql/,另外,我们有有一个database,名为mytest。在数据库mytest中,有一个表,名为erp,执行下列命令


mysql> system ls -l /data/mysql/mytest/

得到下面的输出(我过滤了一下)


-rw-r----- 1 mysql mysql  9023 8 18 05:21 erp.frm
-rw-r----- 1 mysql mysql 2356792000512 8 18 05:21 erp.ibd

frm和ibd的作用,上面介绍过了。现在就是erp.ibd文件太大,所以删除卡住了。

如何解决这个问题呢?

这里需要利用了linux中硬链接的知识,来进行快速删除。下面容我上《鸟哥的私房菜》中的一些内容,

软链接其实大家可以类比理解为windows中的快捷方式,就不多介绍了,主要介绍一下硬链接。

至于这个硬链接,我简单说一下,不想贴一大堆话过来,看起来太累。

就是对于真正存储的文件来说,有一个

然后呢有一个文件名指向上面的node Index

那么,所谓的硬链接,就是不止一个文件名指向node Index,有好几个文件名指向node Index。

假设,这会又有一个文件名指向上面的node Index,即

这个时候,你做了删除文件名(1)的操作,linux系统检测到,还有一个文件名(2)指向node Index,因此并不会真正的把文件删了,而是把步骤(2)的引用给删了,这步操作非常快,毕竟只是删除引用。于是图就变成了这样

接下来,你再做删除文件名(2)的操作,linux系统检测到,没有其他文件名指向该node Index,就会删除真正的存储文件,这步操作,是删真正的文件,所以比较慢。

OK,我们用的就是上面的原理。

先给erp.ibd建立一个硬链接,利用ln命令


system ln /data/mysql/mytest/erp.ibd /data/mysql/mytest/erp.ibd.hdlk

此时,文件目录如下所示

-rw-r----- 1 mysql mysql          9023  8 18 05:21 erp.frm
-rw-r----- 2 mysql mysql 2356792000512  8 18 05:21 erp.ibd
-rw-r----- 2 mysql mysql 2356792000512  8 18 05:21 erp.ibd.hdlk

你会发现,多了一个erp.ibd.hdlk文件,且erp.ibd和erp.ibd.hdlk的inode均为2。

此时,你执行drop table操作


mysql> drop table erp;
Query OK, 0 rows affected (0.99 sec)

你会发现,不到1秒就删除了。因为,此时有两个文件名称(erp.ibd和erp.ibd.hdlk),同时指向一个inode.这个时候,执行删除操作,只是把引用给删了,所以非常快。

那么,这时的删除,已经把table从mysql中删除。但是磁盘空间,还没释放,因为还剩一个文件erp.ibd.hdlk。

如何正确的删除erp.ibd.hdlk呢?

如果你没啥经验,一定会回答我,用rm命令来删。这里需要说明的是,在生产环境,直接用rm命令来删大文件,会造成磁盘IO开销飙升,CPU负载过高,是会影响其他程序运行的。

那么,这种时候,就是应该用truncate命令来删,truncate命令在coreutils工具集中。

详情,大家可以去百度一下,有人对rm和truncate命令,专程测试过,truncate命令对磁盘IO,CPU负载几乎无影响。

删除脚本如下


TRUNCATE=/usr/local/bin/truncate
for i in `seq 2194 -10 10 `;
do sleep 2$TRUNCATE -s ${i}G /data/mysql/mytest/erp.ibd.hdlk
done
rm -rf /data/mysql/mytest/erp.ibd.hdlk ;

从2194G开始,每次缩减10G,停2秒,继续,直到文件只剩10G,最后使用rm命令删除剩余的部分。

其他情况

这里指的是,如果数据库是部署在windows上怎么办。这个问题,我来回答,其实不够专业。因为我出道以来,还没碰到过,生产环境上,mysql是部在windows上的。假设真的碰到了,windows下有一个工具叫mklink,是在windows下创建硬链接锁用,应该能完成类似功能

总结

本文所讲的内容,中小型公司的研发比较容易遇到。因为中小型公司没有专业的DBA,研发童鞋啥都得干。希望大家有所收获吧。



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         小麦苗的微店

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

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26736162/viewspace-2143135/,如需转载,请注明出处,否则将追究法律责任。

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

  1. python合并txt文本_Python实现将目录中TXT合并成一个大TXT文件的方法

    本文实例讲述了Python实现将目录中TXT合并成一个大TXT文件的方法.分享给大家供大家参考.具体如下: 在网上下了一个dota的英雄攻略,TXT格式,每个英雄一个文件,看得疼,就写了一个小东西,合 ...

  2. MySQL把一个大表拆分多个表后,如何解决跨表查询效率问题

    MySQL把一个大表拆分多个表后,如何解决跨表查询效率问题 参考文章: (1)MySQL把一个大表拆分多个表后,如何解决跨表查询效率问题 (2)https://www.cnblogs.com/lili ...

  3. MySQL中的级联删除与更新策略on delete restrict on update restrict

    MySQL中的级联删除与更新策略on delete restrict on update restrict 在MySQL中,当我们执行级联删除与级联更新时,可能会执行On Delete Restric ...

  4. Mysql中的行级锁、表级锁、页级锁

    转载自 Mysql中的行级锁.表级锁.页级锁 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在数据库的锁机制中介绍过,在DBMS中,可以按 ...

  5. 给一个大表增加一个字段,带默认值

    转载自:http://www.itpub.net/forum.php?mod=viewthread&tid=1083259&highlight= 给一个大表增加一个字段,给怎样操作. ...

  6. mysql查看当前数据库中表明,MySQL中查看当前数据库的所有表

    关键词 MySQL数据库 表 摘要 本文介绍在MySQL数据库中,如何列出并查看当前数据库的所有表. 本文介绍在MySQL数据库中,如何列出并查看当前数据库的所有表. 我们创建一个数据库之后,数据库里 ...

  7. mysql中删除某一纵的方法_sql数据库:如何在一个表中填加或者删除一个字段!...

    如要在一个hwsp表中填加字段:ylxs alter table hwsp add column ylxs ALTER TABLE 表 {ADD ADD{COLUMN 字段类型 [ (字长)] [NO ...

  8. rm如何在Linux中删除一个大文件

    rm -rf命令是删除文件夹及其内容最快的方式之一. 仅仅一丁点的敲错或无知都可能导致不可恢复的系统崩坏. 下列是一些rm 命令的选项: rm 命令在Linux下通常用来删除文件. rm -r 命令递 ...

  9. mysql 出现撇号 _Navicat使用教程:如何在MySQL中定位和删除有重复意义的值

    Navicat Premium是一个可连接多种数据库的管理工具,它可以让你以单一程序同时连接到MySQL.Oracle及PostgreSQL数据库,让管理不同类型的数据库更加的方便. DBA最大的麻烦 ...

最新文章

  1. 黑客用python还是ruby-Python、Ruby、Go语言哪个更值得学习?
  2. C#线程--5.0之前时代(一)--- 原理和基本使用
  3. vue中computed、metfods、watch的区别
  4. maven学习(1)
  5. XML与Java 解析方式
  6. Kafka(下):Kafka消费者API,producer拦截器(interceptor)及案例,kafka流Streams,Stream数据清洗案例,Kafka配置信息,flume对接Kafka
  7. python文档自动翻译
  8. Tomcat安装配置(详细步骤)
  9. 静态网站生成器(开源项目)
  10. Win8笔记本不能正常关机或重启
  11. android 65536
  12. 深度学习—数据处理常用代码Python合集
  13. 《解剖PetShop》系列之五
  14. 社交巨头facebook下的messenger推出一项新功能——可以确定你的实时位置信息
  15. SetFocus()函数
  16. 福克斯连接android手机,福克斯改装安卓9寸大屏幕导航和行车记录仪
  17. 北京交通大学计算机保研清华,北京交通大学就读是什么体验?保研率超高!
  18. 局域网文件服务器怎么备份数据,局域网文件备份软件的使用教程
  19. 科研日记1——RSOFT层状结构波导背景折射率?
  20. 将Firefox浏览器的界面语言设置为英文

热门文章

  1. java(double/float)向上取整,向下取整,四舍五入
  2. Excel条件求和函数的超实用技能,真的都掌握了吗?
  3. 在html上js添加宽度,js 获取div高度并重新设置div高度与宽度
  4. 数据革命在危机中诞生 援助组织尝试灵活方法拨开战争迷雾
  5. 世界文化美学知识复习
  6. Y轴的数据莫名其妙不从0开始显示刻度, 而直接显示给定的y的数据
  7. monolog深度使用
  8. 如何改变照片的大小kb?照片怎么改到100kb?
  9. 老公想去跑滴滴,请问收入怎么样?
  10. 【Rider】更改字体大小