前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何快速删除InnoDB中的大表?

如何快速删除InnoDB中的大表?

作者头像
腾讯数据库技术
发布于 2018-06-05 09:09:45
发布于 2018-06-05 09:09:45
8.9K00
代码可运行
举报
运行总次数:0
代码可运行

1. 背景

在使用MySQL时,如果有大表的存储引擎是InnoDB,并且系统参数innodb_file_per_table设置为1,即每个文件对应一个独立的表空间,当对这些大表进行DROP TABLE时,有时会发现整个数据库系统的性能会有显著下降,包括一些只涉及几行数据的简单SELECT查询和DML语句,而且这些语句和正在删除的大表没有关系。造成这种现象的原因是什么呢?通过什么方式能缓解和避免这个问题呢?

2. 已知的瓶颈

Percona曾经在MySQL官方5.5.23之前的版本中遇到过这个问题,并且提供了一种叫Percona Lazy Drop的补丁。简单来说,他们认为这个问题的瓶颈在CPU。在删除一个有独立表空间的大表时,需要对buffer pool中所有和这个表空间有关的数据页做清理工作,包括从AHI,flush list和LRU list上移除,而在这个清理过程中,会一直持有buffer pool的mutex。如果buffer pool配置特别大,比如500 GB大小,持有这个mutex的事件会较长,导致其他连接被阻塞住,从而导致系统性能的下降。Percona Lazy Drop就是在清理buffer pool这里做了优化,尽量短时间和小粒度的持有mutex。

MySQL官方在5.5.23版本中也实现了一个lazy drop的功能,但和Percona的实现方式不一样:在移除flush list时,会有一个条件判断,如果已经处理了超过一定数量的page,会强制释放当前持有的buffer pool mutex和flush list mutex,并且让出CPU,过一会儿再重新拿回锁继续清理flush list;对于LRU list,则不做处理,因为当这个表被删除后,这些数据页最终会在LRU算法调度下被回收。相关的函数调用图为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
buf_LRU_flush_or_remove_pages(BUF_REMOVE_FLUSH_NO_WRITE) --> buf_LRU_remove_pages --> buf_flush_dirty_pages --> buf_pool_mutex_enter
                                                                                                            |__ buf_flush_or_remove_pages --> buf_flush_list_mutex_enter
                                                                                                            |                             |__ buf_flush_try_yield
                                                                                                            |                             |__ buf_flush_list_mutex_exit
                                                                                                            |__ buf_pool_mutex_exit

Percona在后续版本中移植了MySQL官方5.5.23中的lazy drop,并且移除了自己之前实现的Percona Lazy Drop方案。

3. IO问题

尽管已经有了上述的buffer pool层面的优化,我们在使用MySQL 5.6或者5.7时依然发现删除大表对系统性能还是会产生显著的影响,说明DROP TABLE还有其他的性能瓶颈,尤其是对于这样一种业务场景:并发地删除多个大表。在这种场景下,数据库实例几乎处于不可服务的状态。通过抓取这种状态下的mysqld进程的堆栈,我们发现此时性能瓶颈不在上面介绍的buffer pool mutex上,而是在删除ibd文件的IO上。IO的瓶颈是怎样具体地导致系统性能下降的呢?通过阅读MySQL 5.7的源码可以看到,整个DROP TABLE过程可以简单地概括为:

  • 获取dict_sys->mutex这个数据字典锁
  • 启动一个innodb事务
  • 更新数据字典,包括内存中的数据和mysql库下的数据字典表
  • lazy drop逻辑,清理buffer pool的flush list,会多次持有和释放buffer pool mutex以及flush list mutex
  • 写入MLOG_FILE_DELETE类型的redo日志
  • unlink ibd文件
  • 提交innodb事务
  • 释放dict_sys->mutex

这个过程表明,删除ibd文件时是持有dict_sys->mutex的,如果文件大小很大,比如50GB以上,unlink操作会比较耗时,dict_sys->mutex会较长时间被当前连接持有,此时,并发的其他DROP TABLE会阻塞在dict_sys->mutex上,更糟糕的是,并发的被阻塞的DROP TABLE会持有所有的table cache lock,因为它是在清理table cache中和该表相关的数据时被dict_sys->mutex阻塞的,于是,会导致接下来的几乎所有语句都阻塞在table cache lock上,从show processlist结果上看,就表现为SELECT和DML语句状态是”Opening tables”,而DROP TABLE语句状态为”Checking permissions”。被阻塞的DROP TABLE语句(持有所有table cache lock)的相关函数调用为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mysql_execute_command --> mysql_rm_table --> tdc_remove_table --> table_cache_manager.lock_all_and_tdc
                                                              |__ Table_cache_manager::free_table --> intern_close_table --> closefrm --> ha_innobase::close --> row_prebuilt_free --> dict_table_close --> mutex_enter(&dict_sys->mutex)
                                                              |__ table_cache_manager.unlock_all_and_tdc

DROP TABLE的源代码调用关系大致为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
row_drop_table_for_mysql --> row_mysql_lock_data_dictionary
                         |__ trx_start_for_ddl
                         |__ clean up data dictionary
                         |__ row_drop_table_from_cache
                         |__ row_drop_single_table_tablespace --> fil_delete_tablespace --> buf_LRU_flush_or_remove_pages
                         |                                                              |__ os_file_delete --> unlink
                         |__ row_mysql_unlock_data_dictionary

4. 解决方案

从上面介绍可以看到,DROP TABLE可能存在两个性能瓶颈,一个是buffer pool的清理,另一个是ibd文件的删除,怎么缓解或者解决这个问题呢?

4.1 不改动源码情况
  • 尽可能在低峰期进行删除表的操作;
  • 对于buffer pool问题,适当增大innodb_buffer_pool_instances参数,尽量减小持有buffer pool mutex对其他语句的影响;
  • 对于IO问题,删除表之前对ibd文件手动创建一个硬链接,让DROP TABLE可以快速执行结束,等到低峰期再真正从磁盘上删除文件;
4.2 改动源码方案
  • 考虑在unlink文件前释放dict_sys->mutex dict_sys->mutex是用来保护内存中的数据字典,以及mysql库下的数据字典表,从源码可以看到,在unlink ibd文件之前,所有的数据字典操作已经结束,其实是可以释放掉dict_sys->mutex的。 这个方案可以快速简单地解决dict_sys->mutex是性能瓶颈的问题,但是,这个方案是不安全的,因为提前释放dict_sys->mutex意味着需要提前提交innodb事务,于是上述的DROP TABLE过程变为: 那么就会存在这样一个情况:如果系统crash发生在释放dict_sys->mutex后和unlink文件前,那么当数据库重新启动后,从InnoDB数据字典的角度看,DROP TABLE事务已经成功提交了,数据字典里已经没有这个表了,但是磁盘上还存在ibd文件;这个问题一方面会导致磁盘空间的浪费,另外一方面会导致CREATE TABLE失败,如果表名和之前删除的表名一样。可能有人会问,不是在提交事务前写入了一条MLOG_FILE_DELETE类型的redo日志吗,那么数据库启动后重做redo日志时难道不会删除磁盘上遗留的ibd文件?遗憾的是,现在crash recovery的逻辑中,对于MLOG_FILE_DELETE类型的日志,只把它当作是一条“告知”含义的日志记录,不会去删除本应被删除的文件(在UNIV_HOTBACKUP代码分支的crash recovery逻辑中会,但这个分支不在正常的server编译路径中)。 如果想要用这个方案,就需要修改MLOG_FILE_DELETE日志的语义,也就是说在crash recovery中,当执行这条日志时,如果磁盘上该文件还存在,则将该文件删除,同时,将DROP TABLE过程调整为:
    • 获取dict_sys->mutex这个数据字典锁
    • 启动一个innodb事务
    • 更新数据字典,包括内存中的数据和mysql库下的数据字典表
    • lazy drop逻辑,清理buffer pool的flush list,会多次持有和释放buffer pool mutex以及flush list mutex
    • 启动一个mini-transaction
    • 写入MLOG_FILE_DELETE类型的redo日志
    • 提交innodb事务
    • 释放dict_sys->mutex
    • 提交mini-transaction
    • unlink ibd文件
    • 获取dict_sys->mutex这个数据字典锁
    • 启动一个innodb事务
    • 更新数据字典,包括内存中的数据和mysql库下的数据字典表
    • lazy drop逻辑,清理buffer pool的flush list,会多次持有和释放buffer pool mutex以及flush list mutex
    • 写入MLOG_FILE_DELETE类型的redo日志
    • 提交innodb事务
    • 释放dict_sys->mutex
    • unlink ibd文件
  • 假设已经没有dict_sys->mutex瓶颈,单纯地unlink一个大文件也会影响系统其他的IO操作,因为需要涉及大量的文件系统日志操作(详见之前推送的文章”Linux删除文件过程解析”),所以另一个可以考虑的方案是将一个大文件的删除分成多次的truncate操作。具体来说,在DROP TABLE中,将之前的unlink调用替换为rename,将ibd文件加上一个后缀,比如.trash,然后将这个重命名后的文件加入到一个队列中,DROP TABLE就继续后面的提交事务释放锁。真正的文件删除可以在innodb master thread中进行,或者重新启动一条专门的线程负责在后台从队列中拿文件并小批量truncate。 这个方案需要注意的一个问题是重命名的文件名不能重复,因为有dict_syc->mutex的保护,用一个简单的计数器就可以实现,但考虑到重启的情况,用时间戳会更好一些;另一个问题是,如果重命名的文件依然在之前的数据库目录下,那么在后台线程真正删除掉文件之前,DROP DATABASE会失败,一种方案是DBA可以手动删除掉trash文件,另一个方案是让用户指定一个其他的临时目录来存放rename后的文件,注意临时文件目录需要和数据目录在同一个挂载点下。

5. 总结

本文介绍了MySQL DROP TABLE可能存在的性能瓶颈,导致瓶颈的具体原因,以及相关的解决方案和思路。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-12-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯数据库技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
使用HAI,基于PyTorch 实现一个基于 Transformer 架构的字符级语言模型
这篇教程将带你一步步在 JupyterLab 中实现一个简单的语言模型。我们将从零开始,使用 PyTorch 实现一个基于 Transformer 架构的字符级语言模型。尽管在实际应用中,大多数人更倾向于使用 Hugging Face 的预训练模型,但本文的目的是让你了解语言模型的基本原理和实现步骤。接下来,我们会讲解数据预处理、模型构建、训练过程以及如何利用模型生成文本,每个环节都附有详细的代码和解释,力求让内容通俗易懂。
不惑
2025/03/26
3050
使用HAI,基于PyTorch 实现一个基于 Transformer 架构的字符级语言模型
明天下雨还是天晴?这 3 款天气小程序告诉你
可总会有那么几天,穿着短袖出去被冻成狗。又或是出门没带伞,走在半路突然被淋成狗……
知晓君
2018/08/01
1K0
明天下雨还是天晴?这 3 款天气小程序告诉你
这款简洁又漂亮的小程序,让你完美避开下雨天
你是否也遇到过这种情况:看了昨晚的天气预报,说今天不会下雨,心里想着明天休息日可以开心地去逛街。
知晓君
2018/08/01
6050
这款简洁又漂亮的小程序,让你完美避开下雨天
有了这 4 款小程序,天上「下开水」也不怕
而广州,则是高温预警和暴雨预警齐齐发布,小伙伴们纷纷吐槽——这是要「下开水」的节奏啊。
知晓君
2018/08/01
4950
身体健康最重要!这款小程序,告诉你今天用不用戴口罩
对于我们来说,「雾霾」绝对是一个令人恐惧的词,因为,雾霾带来的无形伤害我们根本无法预见。
知晓君
2018/07/30
3690
Python3:获取天气信息
防伪码:没有相当程度的孤独是不可能有内心的平和。 Python版本 Python3.5.3 天气预报 Web 服务参考 http://www.webxml.com.cn/WebServices/Wea
py3study
2020/01/03
1.1K0
天气预报微信推送2020.11.2
http://tianqi.2345.com/wea_history/59431.htm
用户7138673
2022/09/21
1.5K0
天气预报微信推送2020.11.2
java调用天气预报的webservice
天气预报的webService地址:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx
张哥编程
2024/12/17
2170
java调用天气预报的webservice
这个由设计师亲手开发的小程序,就是这么简洁好看 | 晓组织 #16
我热爱生活,是个理想主义者,也是个射手座。我热爱文学,却学了设计,我热爱设计,却学了开发。我想,我所做的一切,只是想更准确地表达自己。
知晓君
2018/08/01
4030
Swift 周报 第十三期
本期是 Swift 编辑组自主整理周报的第四期,每个模块还在调整磨合期。各位读者如果有好的提议,欢迎在文末留言。
Swift社区
2022/12/12
1.8K0
Swift 周报 第十三期
16GB 用户请拿好!这些偶尔才用一次的 App,用小程序就够啦
如果你还没有给自己以戴上一顶,不用急,知晓君这里有一个好方法,能帮你帮轻松地「一键戴帽」,迅速赶上潮流。
知晓君
2018/07/26
4200
Python爬取天气数据及可视化分析!
来源丨Python之王 Python爬取天气数据及可视化分析 说在前面 天气预报我们每天都会关注,我们可以根据未来的天气增减衣物、安排出行,每天的气温、风速风向、相对湿度、空气质量等成为关注的焦点。本次使用python中requests和BeautifulSoup库对中国天气网当天和未来14天的数据进行爬取,保存为csv文件,之后用matplotlib、numpy、pandas对数据进行可视化处理和分析,得到温湿度度变化曲线、空气质量图、风向雷达图等结果,为获得未来天气信息提供了有效方法。 1.数据获取
张俊红
2022/04/06
1.5K0
Python爬取天气数据及可视化分析!
快收下这 5 个小程序!不然,你很可能活不过这个冬天
马上要步入 12 月份,北方的一些地区已经迎来了今年的第一场雪。然而,广州却还是入冬失败,依旧温暖如春。
知晓君
2018/07/27
3220
数读城市:泉州近8年天气和气候分析
本文的主要目的是研究泉州近8年来天气特征以及气候特征,研究二者之间的相关关系,并且对未来的天气和气候情况做预测分析,主要使用的数据如下:
沉默的白面书生
2018/09/30
4.9K1
数读城市:泉州近8年天气和气候分析
推荐几个天气Api接口 (可在小程序中使用)
免费版支持获取国内369个地级市、天气实况(2项)、3天天气预报、生活指数(基础6项)、访问量限额:400次/小时
李光春
2018/09/23
14.4K0
推荐几个天气Api接口 (可在小程序中使用)
天气预报微信推送2020.11.3
http://tianqi.2345.com/wea_history/59431.htm
用户7138673
2022/09/21
1.4K0
天气预报微信推送2020.11.3
小Q-免费的数据能做大事情之天气部分未完待续,持续更新中
开篇 北京的雾霾天气越来越严重了,连外国人都知道,那北京当做案例来讲了,(下附视频连接) http://mp.weixin.qq.com/s?__biz=MzI5NzExNjQ5Mg==&mid=2
GuangdongQi
2018/05/24
7040
R语言对某地天气和温度的分析及预测
历史天气数据来源:http://tianqi.2345.com/wea_history/54511.htm,这是北京的历史数据,采样城市北京、上海、苏州、长沙、广州、一共采集了2011-1-1到2015-4-2这四年三个月共1542(354+366+365+365+92)天的天气数据,其中2011-1-17到2011-1-25这十天的数据缺失,查了多个网站都发现这种情况,就没有把数据补齐了。另外,上海、苏州、广州这三个城市2012-1-15这天,长沙2015-2-10这天,五个城市2014-3-8这天的数据
机器学习AI算法工程
2018/03/13
4.5K0
R语言对某地天气和温度的分析及预测
最新 10 款小程序,最后一个脑洞真大 | 晓榜
赏花时,除了用「形色识花」小程序帮你优雅装 X ,本期「晓榜」选出的这 10 款最新小程序,想必也一定有你需要的。
知晓君
2018/08/01
6540
最新 10 款小程序,最后一个脑洞真大 | 晓榜
python3获取网页天气预报信息并打印
查到一个可以提供区域天气预报的url,说明文档在https://www.sojson.com/blog/234.html,
BH8ANK
2021/01/29
5030
推荐阅读
相关推荐
使用HAI,基于PyTorch 实现一个基于 Transformer 架构的字符级语言模型
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验