暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

mysql加速删除表

原创 黄江平 2022-09-18
664

1.删除表关联的操作

在实际生产环境中,要删除大表,是一个隐含影响性能及业务的操作。当一个表被删除(或截断)时,InnoDB必须扫描整个缓冲池的页面,并删除所有属于该表的页面。对于大型缓冲池,这种在缓冲池页面中的扫描和驱逐过程将会较慢。当我们说“扫描缓冲池”时,它主要查找“LRU”、“FLUSH”(脏页)和“AHI”页。

LRU:缓冲池页面按使用顺序存储在页面链表中。当数据到达列表的末尾时,它将被删除,以便为新数据腾出空间。当需要向缓冲池中添加新页面时,将删除最近最少使用的页面,并将新页面添加到列表的中间。

AHI:这是一个包含频繁访问的索引页的哈希索引。InnoDB有一个监视索引搜索的机制。如果InnoDB注意到查询可以从建立哈希索引中获益,它就会自动这么做。(生产环境一般都关闭AHI)。MySQL 8.0.23开始,这个删除表的过程得到了改进,MySQL不再等待删除。InnoDB为缓冲池中相应的页面驱逐会延生执行。

Show engine innodb status 的 buffer pool片段如下:
BUFFER POOL AND MEMORY

Total large memory allocated 137428992
Dictionary memory allocated 170100
Buffer pool size 8192
Free buffers 7854
Database pages 338
Old database pages 0
Modified db pages 0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 303, created 35, written 39
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 338, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

“Database Pages” 和 “LRU len” 表示需要扫描的页数,
当扫描buffer pool中所有关联的页后,接下来就是操作系统层删除对应的数据文件。删除操作所需要的时间,取决于文件多大,操作系统繁忙程度和当时的系统IO能力。
删除表(drop table)一般有如下2个步骤操作:
1.遍历缓冲池并驱逐找到的相关页面
2.从磁盘删除数据文件

2.加速删除方法探讨

2.1如果缓冲池很大,链表也很大。 我们可以暂时减少缓冲池,使链表更小,这样可以节省扫描buffer pool时间。

操作步骤如下:保存当前缓冲池状态>减少缓冲池大小>删除表(扫描小列表)> reset buffer pool-size >恢复缓冲池内容。
SET GLOBAL innodb_buffer_pool_dump_now=ON;
SHOW STATUS LIKE ‘Innodb_buffer_pool_dump_status’;
SET GLOBAL innodb_buffer_pool_size=128M;
DROP TABLE LARGE_TABLE;
SET GLOBAL innodb_buffer_pool_size=1T;
SET GLOBAL innodb_buffer_pool_load_now=ON;
SHOW STATUS LIKE ‘Innodb_buffer_pool_dump_status’;
这方法看起来不错,但实际生产不会这么操作,原因如下:
1.缓冲池调整大小是一个阻塞操作,它仍然需要扫描列表,整理碎片和调整缓冲池的大小
2.在繁忙的系统上执resize操作严重影响性能
参考:https://dev.mysql.com/doc/refman/5.7/en/innodb-buffer-pool-resize.html

2.2停止使用表(因表要删除,可以停止对表DML操作)
通过回收权限,让应用不操作此表,这将导致缓冲池缓慢地将页面驱逐,取决于mysql繁忙程度。总而言之,对于MySQL级别,您无法避免遍历缓冲池的链表,但通过等待并让缓冲池最终将其驱逐出去,您可以在驱逐过程中节省一些时间。

2.3从磁盘删除文件
现在,这个任务取决于磁盘的繁忙程度和速度。文件删除操作越慢,MySQL返回“删除成功”所需的时间就越长。那么我们有什么手段可以提高这个删除操作速度吗?
我们可以使用硬链接“欺骗MySQL”,让它相信表的数据文件被删除了。
操作步骤如下:
假如要删除test2表
ln test2.ibd test2.ibd_bak
[root@testdb test]# ls -li test2
1871378 -rw-r----- 1 root root 8652 Jun 20 11:30 test2.frm
1871379 -rw-r----- 2 root root 98304 Jun 20 11:32 test2.ibd
1871379 -rw-r----- 2 root root 98304 Jun 20 11:32 test2.ibd_bak

mysql [localhost:5727] {root} (test) > set SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)

mysql [localhost:5727] {root} (test) > drop table if exists test2;
Query OK, 0 rows affected (0.00 sec)

由于刚刚创建了硬链接,删除表只会删除test2,原始数据仍然存在,但是MySQL不知道这些剩余的数据。
再通过truncate命令减小数据文件大小。
[root@testdb test]# truncate -s -1GB test2.ibd_bak
[root@testdb test]#
直到文件变小后,直接rm掉
[root@testdb test]# rm -rf test2.ibd_bak
[root@testdb test]#

在主从环境上,先在从库上操作,从库操作没问题后,再到主库上操作。确保没问题。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论