CentOS 7 下 MySQL 5.7 删除大表更快的方法

前言

MySQL 删除大表速度相对很慢,而且在 drop table 的时候,所有进程不管是 DDL 还是 DML 都被挂起,直到 drop table 结束才继续执行,这严重影响线上应用的使用。

这是因为 InnoDB 会维护一个全局独占锁(在table cache上面),直到 drop table 完成才释放。而且如果表文件过大,直接删除会瞬时占用大量IO,造成IO阻塞。

下面我们介绍一个快速 drop table 的方法,不管多大的表,InnoDB 都可以很快返回,表删除完成。主要是使用硬链接快速删除大表的步骤。

环境说明

CentOS 7(Minimal Install)

$ cat /etc/redhat-release 
CentOS Linux release 7.5.1804 (Core) 

MySQL 版本为 5.7

$ mysql -u root -p
mysql> select @@version;
+------------+
| @@version  |
+------------+
| 5.7.23-log |
+------------+
1 row in set (0.00 sec)

mysql> exit
Bye

步骤

步骤 1: 确认数据目录

查看 MySQL 数据库目录

$ mysql -u root -p
mysql> select @@datadir;
+-----------------+
| @@datadir       |
+-----------------+
| /var/lib/mysql/ |
+-----------------+
1 row in set (0.00 sec)

mysql> exit
Bye

使用 root 用户到 MySQL 的 datadir 目录下,

$ sudo su root -
Password: 
# cd /var/lib/mysql/yourdatabase

注意

请将 yourdatabase 替换为您的数据库名称

步骤 2: 建立硬链接

先找到要删除的大表

# ls -lhSr mybigtable*
-rw-r-----. 1 mysql mysql   30K Aug 16 08:46 mybigtable.frm
-rw-r-----. 1 mysql mysql 99.2G Aug 16 08:46 mybigtable.ibd

然后建立硬链接,本例添加 hdlk 后缀,后缀可任意修改。

# ln mybigtable.ibd mybigtable.ibd.hdlk

再次查看

# ls -lhSr mybigtable*
-rw-r-----. 1 mysql mysql   30K Aug 16 08:46 mybigtable.frm
-rw-r-----. 2 mysql mysql 99.2G Aug 16 08:46 mybigtable.ibd
-rw-r-----. 2 mysql mysql 99.2G Aug 16 08:46 mybigtable.ibd.hdlk

注意

可以看到此时 mybigtable.ibd 的文件引用数由 1 变为 2。

步骤 3: 删除大表

进入 MySQL, 删除大表

$ mysql -u root -p
Enter password:
mysql> drop table mybigtable;
Query Ok, 0 rows affacted(0.02 sec)

我们会发现删除得非常快,因为其直接的物理文件块没有被删除.只是删除了一个指针而已,当 INODE 的引用数 N=1 时, 删除文件需要去把这个文件相关的所有数据块清除,所以会比较耗时。

注意

有时数据库使用外键约束,造成删除不成功。
Cannot delete or update a parent row: a foreign key constraint fails

先确认表肯定要删除,确认之后,在本次会话设置 FOREIGN_KEY_CHECKS 变量来避免这种情况。

mysql> SET FOREIGN_KEY_CHECKS = 0;
Query OK, 0 rows affected (0.01 sec)

mysql> drop table mybigtable;
Query Ok, 0 rows affacted(0.02 sec)

mysql> SET FOREIGN_KEY_CHECKS = 1;
Query OK, 0 rows affected (0.00 sec)

mysql> exit
Bye

此时再去 MySQL 的 datadir 目录查看

# cd /var/lib/mysql/yourdatabase
# ls -lhSr mybigtable*
-rw-r-----. 1 mysql mysql 99.2G Aug 16 08:46 mybigtable.ibd.hdlk

发现 mybigtable.ibd 已经被删除,同时文件引用数变为 1。

此时,我们删除这个大文件即可。

# rm mybigtable.ibd.hdlk

至此,MySQL 5.7 删除了大表,而且非常快。

结论

本文演示了 CentOS 7 下 MySQL 5.7 快速删除大表的方法。

参考资料

mysql删除大表更快的drop table办法
mysql删除报错Cannot delete or update a parent row

分类: Linux | 评论

blog comments powered by Disqus