磁盘剩余空间策略_MySQL磁盘消耗迅猛掌握这点就够了,包你事半功倍

e21fb34b2376420b66042c7b6c0a557e.png

Part1:写在最前

当一张单表10亿数据量的表放在你面前,你将面临着什么?

Part2:背景介绍

为了提升数据库资源利用率,一个实例中,在不互相影响,保证业务高效的前提下,我们会将同一个大业务下的不同小业务放在一个实例中,我们的磁盘空间是2T,告警阈值为当磁盘剩余空间10%时发出短信告警。笔者接到某业务主库磁盘剩余空间告警的短信后,经过一番查探,发现从几天前开始,有一张表的数据量增长非常快,而在之前,磁盘空间下降率还是较为平缓的,该表存在大字段text,其大批量写入更新,导致磁盘消耗迅猛。

我们首先来看下该表的表结构:

mysql> CREATE TABLE `tablename_v2` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,`No` varchar(64) NOT NULL DEFAULT '',`Code` varchar(64) NOT NULL DEFAULT '' ,`log` varchar(64) DEFAULT '' ,`log1` varchar(64) DEFAULT '' ,.....`Phone` varchar(20) DEFAULT '',`createTime` bigint(20) unsigned NOT NULL DEFAULT '0',`updateTime` bigint(20) unsigned NOT NULL DEFAULT '0',PRIMARY KEY (`id`),UNIQUE KEY `uk_mailNo` (`No`,`Code`),KEY `idx_Phone` (`Phone`)
) ENGINE=InnoDB AUTO_INCREMENT=9794134664 DEFAULT CHARSET=utf8;

与业务了解得知,该表几乎没有删除操作,由于数据量过大,我们模糊使用auto_increment来作为表数量预估值,避免count()操作对线上造成的影响。

Part3:案例分析

与业务沟通了解后得知,该表可以清理4个月以前的老旧数据,因此可以使用delete的方式清除,而我们通过表结构可以看出,该表在设计之初,并没有对updateTime列创建索引,因此以时间为范围去进行delete操作,这显然是不合理的。

经过与业务协商,我们确定了可以将id作为删除条件,删除id<2577754125之前的数据

也就是说,此时的delete语句变为了:

mysql> delete from tablename_v2 where id <2577754125;

且不说delete操作有多慢,直接执行这样的SQL也会有诸如长事务告警,从库大量延迟等并发症产生,因此绝不能在生产库上进行这种大批量的危险操作。

实战

Part1:监控

从监控图我们能看出磁盘下降的趋势:

2669e6ea77d3e9a1b56d95c819d66747.png

监控显示,从6月14日-6月18日期间,磁盘消耗最为严重,与业务沟通得知,618期间大促引发该表存储量激增导致。

Part2:实战操作

我们通过查看binlog发现,集群中binlog的刷新量虽不说像笔者上个案例那样多么迅猛,但也绝不是老实本分

52fd23c1db75e2bd865bff09c7e78a96.png

我们可以看出,在高峰期间,binlog的刷新间隔最短达到了2分钟写满1.1GB的binlog。因此笔者与业务沟通后,首先清理binlog日志,将 expire_logs_days从7天调整至3天。

同时,清理一些能够清理的无用日志、废旧文件等等。

我们也能在上面的监控图看到在做完这些清理操作后,磁盘空间剩余从4%提升至12%,但随后依旧保持原有速率下降。

Part3:pt-archiver

真凶找到了,我们怎么办,别急,使用pt-archiver。pt-archiver工具是percona工具集的一员,是归档MySQL大表数据的最佳轻量级工具之一。他可以实现分chunk分批次归档和删除数据,能避免一次性操作大量数据带来的各种问题。

闲话不多说,一向本着实战的原则,我们直接上命令:

pt-archiver --source
h=c3-helei-db01.bj,D=helei,t=tablename_v2,u=sys_admin,p=MANAGER
--where 'id<2577754125' --purge --progress 10000 --limit=10000
--no-check-charset --txn-size=10000 --bulk-delete --statistics --max-lag=20
--check-slave-lag c3-helei-db02.bj

简单说下常用的参数:

3c7caf51053ce39f60793958832391c1.png

Warning:警告这里就又有个小坑了,的确,我们使用bulk-delete参数能够增加删除速率,相比不使用bulk-delete速度能够提升10倍左右,但问题也就显现出来,在使用上述命令期间,发现binlog每秒写入量激增,这又回到了我们说的,哪些情况会导致binlog转为row格式。

首先我们需要了解到使用bulk-delete时,sql是如下执行的:

mysql> delete from tablename_v2 where id >xxx and id < xxx limit 10000.

如果您之前关注过笔者的文章,应该知道,当使用了delete from xxx where xxx limit 语法时,会将binlog_format从mixed转为row,这样的话,删除的同时,binlog由于转为了row格式也在激增,这与我们的预期是不符的。

因此最终的命令为:

pt-archiver --source
h=c3-helei-db01.bj,D=helei,t=tablename_v2,u=sys_admin,p=MANAGER
--where 'id<2577754125' --purge --progress 10000 --limit=10000
--no-check-charset --txn-size=10000  --statistics --max-lag=20
--check-slave-lag c3-helei-db02.bj

去掉了bulk-delete,这样的话就能够保证正常的delete,而不加limit,binlog不会转为row格式导致磁盘消耗继续激增。

对于Innodb引擎来说,delete操作并不会立即释放磁盘空间,新的数据会优先填满delete操作后的“空洞”,因此从监控来看就是磁盘不会进一步消耗了,说明我们的pt-archiver工具删除是有效的。

Part4:困惑

首先我们要知道,当你面对一张数据量庞大的表的时候,有些东西就会受限制,例如:

  1. 不能alter操作,因为这会阻塞dml操作。
  2. 对于本案例,空间本就不足,也不能使用pt-online工具来完成。

对于不能alter其实是比较要命的,比如开发要求在某个时间段尽快上线新业务,而新业务需要新增列,此时面对这么庞大的量级,alter操作会异常缓慢。

因此,笔者与研发沟通,尽快采用物理分表的方式解决这个问题,使用物理分表,清理表的操作就会很容易,无需delete,直接drop 老表就可以了。其次,物理分表让alter语句不会卡住太久,使用pt-online工具也不会一次性占据过多的磁盘空间诱发磁盘空间不足的告警。

再有就是迁移TiDB,TiDB相较MySQL更适合存储这类业务。

Part5:再谈binlog_format

我们选取其中高峰期的binlog发现其update操作转为了row格式,记录了所有列变更前后的所有信息,而binlog中并未出现update xxx limit这种操作,那又会是什么引发的row格式记录呢?

这里这篇文章又抛出一个新的案例,在官网那篇何时mixed转row格式中又一个没有记录的情况

官方文档:

When running in MIXED logging format, the server automatically switches from statement-based to row-based logging under the following conditions:
When a DML statement updates an NDBCLUSTER table.
When a function contains UUID().
When one or more tables with AUTO_INCREMENT columns are updated and a trigger or stored function is invoked. Like all other unsafe statements, this generates a warning if binlog_format = STATEMENT.
When any INSERT DELAYED is executed.
When a call to a UDF is involved.
If a statement is logged by row and the session that executed the statement has any temporary tables, logging by row is used for all subsequent statements (except for those accessing temporary tables) until all temporary tables in use by that session are dropped.
This is true whether or not any temporary tables are actually logged.
Temporary tables cannot be logged using row-based format; thus, once row-based logging is used, all subsequent statements using that table are unsafe. The server approximates this condition by treating all statements executed during the session as unsafe until the session no longer holds any temporary tables.
When FOUND_ROWS() or ROW_COUNT() is used. (Bug #12092, Bug #30244)
When USER(), CURRENT_USER(), or CURRENT_USER is used. (Bug #28086)
When a statement refers to one or more system variables. (Bug #31168)

我们这个案例中又出现了一个新的因素就是:

当表结构中存在多个唯一索引(包括主键id),本案例中存在主键和UNIQUE KEY `uk_mailNo`这个唯一索引,且使用了

INSERT ... ON DUPLICATE KEY UPDATE

这时,mysql binlog_format就会被转为row格式,这个内容也是记录在官网的其他章节:

https://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.html

也就是说,只要业务解决了使用这种语法插入的话,磁盘空间下降迅猛的原因也能够缓解不少。我们统计发现,qps更高的其他业务中,binlog保留7天的磁盘消耗量在60GB

而该业务我们仅仅保留3天binlog,却依旧消耗了430GB的磁盘空间,这已经超过了我们整个2T磁盘空间的5分之一了。

总结

通过这个案例,我们能够了解到什么情况下binlog_format会由MIXED格式转为ROW格式,以及触发的一系列并发症和解决办法,还有pt工具pt-archiver的使用。由于笔者的水平有限,编写时间也很仓促,文中难免会出现一些错误或者不准确的地方,不妥之处恳请读者批评指正。喜欢笔者的文章,可以点一波关注,谢谢!

推荐阅读:

n南末余笙:“精神”小伙,开发三年,四面华为,豪横迈进华为​zhuanlan.zhihu.com
7a0d92f5ec2878e920b54c91c6163ac7.png
n南末余笙:历时三个月,我成功拿到了阿里、美团和京东的offer​zhuanlan.zhihu.com
b53c60f2caab4e86a506b6956c16862e.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/431972.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Date Picker控件:

Date Picker控件&#xff1a; 中文&#xff1a;日期/时间选取器UIDatePicker有一个实例方法setDate:animated&#xff0c;以编程的方式选择日期。UIDatePicker有四种模式&#xff08;model&#xff09;&#xff1a;Time&#xff08;只选时间&#xff09;Date&#xff08;只选日…

logback日志pattern_@Slf4j 实现日志输入到外部文件

添加一个配置文件\src\main\resources\logback-spring.xml<?xml version"1.0" encoding"UTF-8"?><configuration scan"true" scanPeriod"10 seconds"> <contextName>logbackcontextName> <prope…

C++ Prime:sizeof运算符

sizeof运算符的结果部分地依赖于其作用的类型&#xff1a; 对char或者类型为char的表达式执行sizeof运算结果得1&#xff1b; 对引用类型执行sizeof运算得到被引用对象所占空间的大小&#xff1b; 对指针执行sizeof运算得到指针本身所占空间的大小&#xff1b; 对解引用指针执行…

前驱和后驱什么意思_为什么只有豪车才敢用后驱

为什么只有豪车才敢用后驱https://www.zhihu.com/video/1156959599864147968一般的家用车&#xff0c;基本上都是前驱为主&#xff0c;前驱够用&#xff0c;成本还低。但前驱满足不了豪华车的运动需求&#xff0c;所以豪华车后驱才是王道。有人这个时候肯定要跳出来不服了&…

leetcode 第五题 Longest Palindromic Substring (java)

Longest Palindromic Substring Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. time255ms accepted 暴力遍历 public String longes…

思科光传输功率查询_常见的6款40G QSFP+光模块型号介绍及应用

近些年来&#xff0c;云计算和大数据在我国兴起一股热潮&#xff0c;为了提供足够的带宽&#xff0c;许多接入交换机已经发展到可以连接40G以太网的核心交换机。互连数据传输的快速发展&#xff0c;离不开40G光模块&#xff0c;因为它可以提供足够的带宽&#xff0c;以确保数据…

sigquit信号默认忽略吗_老妹儿,你真的搞懂了 Shell 信号吗?

作者&#xff1a;李振良OK链接&#xff1a;https://blog.51cto.com/lizhenliang/1899347哈喽&#xff0c;各位新来的小伙伴们&#xff0c;大家好&#xff01;由于公众号做了改版&#xff0c;为了保证公众号的资源能准时推送到你手里&#xff0c;大家记得将咱们的公众号 加星标置…

wget 命令用法详解

wget是在Linux下开发的开放源代码的软件&#xff0c;作者是Hrvoje Niksic&#xff0c;后来被移植到包括Windows在内的各个平台上。它有以下功能和特点&#xff1a; &#xff08;1&#xff09;支持断点下传功能&#xff1b;这一点&#xff0c;也是网络蚂蚁和FlashGet当年最大的卖…

datetimepicker不可以选择当天之前_专访吴京:网上《战狼3》的消息我都不知道,大家可以选择不信...

搜狐娱乐讯 (哈麦/文)在2017爆火的《战狼2》之后&#xff0c;吴京演了《祖宗十九代》《流浪地球》《老师好》《银河补习班》《攀登者》《我和我的祖国》《我和我的家乡》《金刚川》八部电影&#xff0c;但是计划中的《战狼3》一直没有动静。不过&#xff0c;关于《战狼3》&…

机器人蛮王_盖伦:吊打我老婆,蛮王:我也是,他:被老婆打的不敢出塔

相遇就是缘分&#xff0c;你点开了我的文章&#xff0c;小编感到万分荣幸&#xff0c;感谢各位朋友。既然看到了我的文章&#xff0c;就说明我们还是有缘&#xff0c;希望大家可以帮我点点左上角的蓝色字体&#xff0c;小编给大家鞠躬了&#xff01;LOL如此好玩的原因&#xff…

栈 详解

官方定义是这样的&#xff1a;栈&#xff08;Stack&#xff09;是一个后进先出的线性表&#xff0c;它要求只在表尾进行删除和插入操作。 栈是一种重要的线性结构&#xff0c;可以这样讲&#xff0c;栈是线性表的一种具体表现形式&#xff0c;但是它在操作上有一些特殊的要求和…

android serialport new 软件退出_基于Android9.0,了解Android启动流程

先记住四个进程和三种方式。**四个进程**1.Launcher进程2.system_server进程3.App进程4.Zygote进程**三种方式**1.Binder方式2.Socket方式3.Handler方式点击桌面APP图标&#xff0c;Launcher调用startActivitySafely&#xff08;Launcher进程&#xff09;java/*** Default laun…

Objective-C 学习笔记

超类 即父类&#xff0c;通过 [super setName: "a"] 可以调用超类方法 复合 是指一个对象由其他多个对象组成 对象初始化 interface Car : NSObject (Engine *engine; ) endimplementation Car - (id) init {  //因init方法可能返回不同的对象&#xff0c;所以需要…

【转】使用命令行方式创建和启动android模拟器

原文网址&#xff1a;http://blog.csdn.net/tiandinilv/article/details/8953001 1、Android模拟器介绍 Android中提供了一个模拟器来模拟ARM核的移动设备。Android的模拟器是基于QEMU开发的&#xff0c;QEMU是一个有名的开源虚拟机项目&#xff08;详见http://bellard.org/qem…

centos7限制cpu使用_Linux系统进程CPU使用率限制脚本

一、背景近日在客户系统运维中发现&#xff0c;有系统在定时脚本执行期间会将Linux系统CPU利用率跑满&#xff0c;导致其他服务受到影响&#xff0c;故查阅资料发现有大神写的CPU利用率限制程序。地址&#xff1a;CPU Usage Limiter for Linux根据此编写脚本&#xff0c;配合定…

LPC1768的SPI通讯

SPI是一种全双工串行接口&#xff0c;可处理多个连接到指定总线上的主机和从机。在数据传输过程中总线上只能有一个主机和一个从机通信。在数据传输中&#xff0c;主机总是会向从机发送一帧8到16个位的数据&#xff0c;而从机也总会向主机发送一帧字节数据 使用代码如下 void S…

python 项目实战视频_腾讯视频 Python 爬虫项目实战

做了一些小项目&#xff0c;用的技术和技巧会比较散比较杂&#xff0c;写一个小品文记录一下&#xff0c;帮助熟悉。需求&#xff1a;经常在腾讯视频上看电影&#xff0c;在影片库里有一个"豆瓣好评"板块。我一般会在这个条目下面挑电影。但是电影很多&#xff0c;又…

Java中文乱码问题(转)

解决JSP中文乱码问题 大家在JSP的开发过程中&#xff0c;经常出现中文乱码的问题&#xff0c;可能一至困扰着大家&#xff0c;现把JSP开发中遇到的中文乱码的问题及解决办法写出来供大家参考。首先了解一下Java中文问题的由来&#xff1a; Java的内核和class文件是基于unicode的…

文本显示变量_几千个IO状态显示.十几分钟搞定实例

工程上常会在一个或者数个界面中对所有IO点监控&#xff0c;很多小伙伴用一一映射的传统方法来实现&#xff0c;在超小型项目中实用性较强&#xff0c;在稍微大一点的项目中实现起来效率低还经常出错。本文旨在分享有价值的实际经验&#xff0c;供小伙伴们参考。在实现监控前要…

贷款购房 房贷 每月还款额是如何计算出来的? 每月还款额计算步骤/方法

http://jingyan.baidu.com/m/article/0eb457e55f23fc03f1a905e5.html购房和贷款是每个普通百姓都关心的事情。贷款购房最基本的问题当然是琢磨贷款、还贷以及还贷年限与自己每月的那点“杯水车薪”收入之间的关系&#xff0c;怎样让它们门当户对起来&#xff0c;如何对着一张载…