日期:2014-05-16 浏览次数:20788 次
author:skate
time:2013/03/01
mysql在线无性能影响删除7G大表
如何在mysql数据库里删除7G(或更大)大表,使其又不影响服务器的io,导致性能下降影响业务。先不说其是mysql表,就是普通文件,如果直接rm删除,也会使服务器的io性能急剧下降;换个思路如果用化整为零的方式,分多次大大文件一点一点删除,就可以避免因删除文件占用太多服务器io资源
例子:
版本:
mysql> select version();
+------------+
| version() |
+------------+
| 5.1.67-log |
+------------+
1 row in set (0.05 sec)
数据表大小:
mysql> select count(1) from user4;
+----------+
| count(1) |
+----------+
| 36700160 |
+----------+
1 row in set (1 min 35.66 sec)
[root@racdb2 test]# ll user_bak*
-rw-rw---- 1 mysql dba 10466 Mar 1 13:50 user4_bak.frm
-rw-rw---- 2 mysql dba 7734296576 Mar 1 14:28 user4_bak.ibd
[root@racdb2 test]#
创建一个中间表,来见减少对业务影响
mysql> create table user4_tmp engine=innodb select * from user4 where 1=2;
Query OK, 0 rows affected (0.18 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| a |
| b |
| user |
| user1 |
| user2 |
| user3 |
| user4 |
| user4_tmp |
| utf8 |
+----------------+
9 rows in set (0.01 sec)
把原始表user4重命名
mysql> rename table user4 to user4_bak;
Query OK, 0 rows affected (0.03 sec)
把中间表重命名为原始表user4,如果需要数据,可以导入部分数据
mysql> rename table user4_tmp to user4;
Query OK, 0 rows affected (0.01 sec)
通过文件的硬链接方式删除文件
[root@racdb2 test]# ln user4_bak.ibd user4_bak.ibd.hdlk
[root@racdb2 test]# ll user_bak*
-rw-rw---- 1 mysql dba 10466 Mar 1 13:50 user4_bak.frm
-rw-rw---- 2 mysql dba 7734296576 Mar 1 14:28 user4_bak.ibd
-rw-rw---- 2 mysql dba 7734296576 Mar 1 14:28 user4_bak.ibd.hdlk
[root@racdb2 test]#
注意:
硬连接的作用是允许一个文件拥有多个有效路径名,即文件的索引节点有一个以上的连接。只删除一个连接并不影响索引节点本身和其它的连接,只有当最后一个连接被删除后,文件的数据块及文件的连接才会被释放。也就是说,文件真正删除的条件是与之相关的所有硬连接文件均被删除。
发现删除7G的文件巨快
mysql> drop table user4_bak;
Query OK, 0 rows affected (0.60 sec)
这个时候在mysql数据库里已经删除了表user4_bak,但系统的存储空间还没有释放,如下所示:
[root@racdb2 test]# ll user_bak*
-rw-rw---- 2 mysql dba 7734296576 Mar 1 14:28 user4_bak.ibd.hdlk
只有我们把文件user4_bak.ibd.hdlk删除,磁盘空间才会被释放,那如何尽量少占用系统资源,最小化影响业务来释放这个空间呢?前面已经分析通过化整为零的方式,通过coreutils工具集中的truncate对大文件进行shrink来逐渐释放空间.
脚本如下:
[root@racdb2 test]# more /home/mysql/rm_bigfile.sh
#!/bin/bash
#author:skate
#time:2013/02/28
#function:rm huge file
TRUNCATE=/usr/local/bin/truncate
for i in `seq 7384 -100 10 `; #从7384开始每次递减100 ,输出结果见下面
do
sleep 1
echo "$TRUNCATE -s ${i}M /tmp/user4_bak.ibd.hdlk "
$TRUNCATE -s ${i}M /mysqldata/data/test/user_bak.ibd.hdlk<