技术分享 | 如何优雅的删除 Zabbix 的 history 相关历史大表

作者:徐文梁

爱可生DBA成员,一个执着于技术的数据库工程师,主要负责数据库日常运维工作。擅长MySQL,redis,其他常见数据库也有涉猎,喜欢垂钓,看书,看风景,结交新朋友。

本文来源:原创投稿

  • 爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

    问题背景:

    前段时间,客户反馈 Zabbix 实例的 history_str 表数据量很大,导致磁盘空间使用率较高,想要清理该表,咨询是否有好的建议。想着正好最近学习了相关的知识点,正好可以检验一下学习成果,经过实践的检验,最终考试合格,客户也比较满意,于是便有了此文。

    问题沟通:

    通过实际查看环境及与客户沟通,得出以下信息:

    1. 现场是双向主从复制架构,未设置从库read_only只读。

    2. history_str 表的ibd数据文件超460G。

    3. history_str 表的存量数据可以直接清理。

    4.现场实例所在的服务器是虚拟机,配置较低。

    因此,综合考虑后建议客户新建相同表结构的表然后对原表进行 drop 操作,但是表数据量比较大,需要考虑以下风险:

    1. drop大表可能会导致实例hang住,影响数据库正常使用。

    2. drop大表操作导致主从延时。

    3. 删除大文件造成磁盘io压力较大。

    最终方案:

    在考虑以上的基础上,最终给出如下方案:

    1. 在主库执行如下命令建立相同表结构表并进行rename操作:

    create table history_str_new like history_str;<br>rename table history_str to history_str_old, history_str_new to<br>history_str;<br>

    2. 在主库和从库执行以下操作,建立硬链接文件:

    ln history_str_old.ibd history_str_old.ibd.hdlk

    3. 完成第二步后,建议间隔一两天再进行操作,让history_str_old 表数据从 innodb buffer pool 中冷却,然后业务低峰期在主从库分别执行如下操作,建议先操作从库,从库验证没问题后再在主库操作:

    set sql log bin=0;       //临时关闭写操作记录binlog<br>drop table history_str_old;//执行drop操作<br>set sql log bin=l;       //恢复写操作记录binlog<br>

    4. 删除 history_old.ibd.hdlk 文件,释放空间,可以通过 linux 的 truncate 命令实现,参考脚本如下:

    #!/bin/bash<br>##############################################################################<br>##           第一个参数为需要执行操作的文件的文件名称                              ##<br>##           第二个参数为每次执行操作的缩减值,单位为MB                            ##<br>##           第三个参数为每次执行后的睡眠时间,单位为S                             ##<br>##############################################################################<br>  <br>fileSize=`du $1|awk -F" " '{print $1}'`<br>fileName=$1<br>chunk=$2<br>sleepTime=$3<br>chunkSize=$(( chunk * 1024 ))<br>rotateTime=$(( fileSize / chunkSize ))<br>declare -a currentSize<br>echo $rotateTime<br>  <br>function truncate_action()<br>{<br>for (( i=0; i<=${rotateTime}; i++ ))<br>do<br>if [ $i -eq 0 ];then<br>echo "开始进行truncate操作,操作文件名为:"$fileName<br>fi<br>  <br>if [ $i -eq ${rotateTime} ];then<br>echo "执行truncate操作结束!!!"<br>fi<br>  <br>truncate -s -${chunk}M $fileName<br>currentSize=`du -sh $fileName|awk -F" " '{print $1}'`<br>echo "当前文件大小为: "$currentSize<br>sleep $sleepTime<br>done<br>}<br>  <br>truncate_action<br>

    示例:sh truncateFile.sh history_str_old.ibd.hdlk 256 1,表示删除 history_str_old.ibd.hdlk 文件,每次截断大小为256M,然后sleep间隔为1s。

    1. 到此,静静等待就行了。无聊的话也可以思考一下人生。

    小知识:

    前面解决了如何操作的问题,但是作为一个称职的DBA,不光要知道如何做,还得知道为什么这么做,不然的话,敲回车键容易,后悔却很难,干货来了,一起了解一下吧。下次遇到类似问题就不慌了。

    tips1:

    mysql删除表的流程:<br>1.持有buffer pool mutex。<br>2.持有buffer pool中的flush list mutex。<br>3.扫描flush list列表,如果脏页属于drop掉的table,则直接将其从flush list列表中移除。如果开启了AHI,还会遍历LRU,删除innodb表的自适应散列索引项,如果mysql版本在5.5.23之前,则直接删除,对于5.5.23及以后版本,如果占用cpu和mutex时间过长,则释放cpu资源,flush list mutex和buffer pool mutex一段时间,并进行context switch。一段时间后重新持有buffer pool mutex,flush list mutex。<br>4.释放flush list mutex。<br>5.释放buffer pool mutex。<br>

    tips2:

    对于linux系统,一个磁盘上的文件可以由多个文件系统的文件引用,且这多个文件完全相同,并指向同一个磁盘上的文件,当删除其中任一一个文件时,并不会删除真实的文件,而是将其被引用的数目减1,只有当被引用数目为0时,才会真正删除文件。<br>

    tips3:

    大表drop或者truncate相关的一些bug:<br> <br>这两个指出drop table 会做两次 LRU 扫描:一次是从 LRU list 中删除表的数据页,一次是删除表的 AHI 条目。<br>https://bugs.mysql.com/bug.php?id=51325<br>https://bugs.mysql.com/bug.php?id=64284<br>  <br>对于分区表,删除多个分区时,删除每个分区都会扫描LRU两次。<br>https://bugs.mysql.com/bug.php?id=61188<br>  <br>truncate table 会扫描 LRU 来删除 AHI,导致性能下降;8.0 已修复,方法是将 truncate 映射成 drop table + create table<br>https://bugs.mysql.com/bug.php?id=68184<br>  <br>drop table 扫描 LRU 删除 AHI 导致信号量等待,造成长时间的阻塞<br>https://bugs.mysql.com/bug.php?id=91977<br>  <br>8.0依旧修复了 truncate table 的问题,但是对于一些查询产生的磁盘临时表(innodb 表),在临时表被删除时,还是会有同样的问题。这个bug在8.0.23中得到修复。<br>https://bugs.mysql.com/bug.php?id=98869<br>

    本文关键字:#MySQL# #大表删除#

    文章推荐:

    故障分析 | MySQL 主从延时值反复跳动

    故障分析 | Greenplum 数据状态异常处理

    故障分析 | Greenplum 集群 standby 故障处理

    关于SQLE

    爱可生开源社区的 SQLE 是一款面向数据库使用者和管理者,支持多场景审核,支持标准化上线流程,原生支持 MySQL 审核且数据库类型可扩展的 SQL 审核工具。

    SQLE 获取

    类型 地址
    版本库 https://github.com/actiontech/sqle
    文档 https://actiontech.github.io/sqle-docs-cn/
    发布信息 https://github.com/actiontech/sqle/releases
    数据审核插件开发文档 https://actiontech.github.io/sqle-docs-cn/3.modules/3.7_auditplugin/auditplugin_development.html

    更多关于 SQLE 的信息和交流,请加入官方QQ交流群:637150065...

本文分享自微信公众号 - 爱可生开源社区(ActiontechOSS)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。