MySQL日志(二):MySQL抖动

一条SQL语句, 正常执行的时候特别快, 但是有时也不知道怎么回事, 它就会变得特别慢, 并且这样的场景很难复现, 它不只随机, 而且持续时间还很短。

看上去, 这就像是数据库“抖”了一下。 今天, 我们就一起来看一看这是什么原因。

你的SQL语句为什么变慢了:在刷脏


很重要:做下类比的话, 掌柜记账的账本是数据文件(磁盘), 记账用的粉板是日志文件(redo log) , 掌柜的记忆就是内存。

掌柜总要找时间把账本更新一下, 这对应的就是把内存里的数据写入磁盘的过程, 术语就是flush。 在这个flush操作执行之前, 孔乙己的赊账总额, 其实跟掌柜手中账本里面的记录是不一致的。 因为孔乙己今天的赊账金额还只在粉板上, 而账本里的记录是老的, 还没把今天的赊账算进去。

当内存数据页跟磁盘数据页内容不一致的时候, 我们称这个内存页为“脏页”。 内存数据写入到磁盘后, 内存和磁盘上的数据页的内容就一致了, 称为“干净页”。

不论是脏页还是干净页, 都在内存中。 在这个例子里, 内存对应的就是掌柜的记忆。

接下来, 我们用一个示意图来展示一下“孔乙己赊账”的整个操作过程(即刷脏过程)。 假设原来孔乙己欠账10文, 这次又要赊9文。

问1:一条SQL语句, 正常执行的时候特别快, 但是有时也不知道怎么回事, 它就会变得特别慢, 并且这样的场景很难复现, 它不只随机, 而且持续时间还很短。看上去, 这就像是数据库“抖”了一下。那么SQL语句为什么突然变慢了?

平时执行很快的更新操作, 其实就是在写内存和日志, 而MySQL偶尔“抖”一下的那个瞬间, 可能就是在刷脏页(flush) 。

问2:什么情况下会引发数据库刷脏(flush)过程呢?

1)InnoDB的redo log写满了。这时候系统会停止所有更新操作, 把checkpoint往前推进, redo log留出空间可以继续写。 对应的是《孔乙己》粉板写满了,这时候如果再有人来赊账, 掌柜就只得放下手里的活儿, 将粉板上的记录擦掉一些, 留出空位以便继续记账。 当然在擦掉之前, 他必须先将正确的账目记录到账本中才行。

注:checkpoint可不是随便往前修改一下位置就可以的。 比如上图, 把checkpoint位置从CP推进到CP’, 就需要将两个点之间的日志(浅绿色部分) , 对应的所有脏页都flush到磁盘上。 之后, 图中从write pos到CP’之间就是可以再写入的redo log的区域。

2)系统内存不足。当需要新的内存页,而内存不够用的时候,就要淘汰一些数据页,空出内存给别的数据页使用。如果淘汰的是“脏页”,就要先将脏页写到磁盘。如果淘汰的是”干净页“,直接淘汰即可。对应的是《孔乙己》这一天生意太好, 要记住的事情太多, 掌柜发现自己快记不住了, 赶紧找出账本把孔乙己这笔账先加进去。

注:如果刷脏页一定会写盘,就保证了每个数据页有两种状态:

  • 一种是内存里存在, 内存里就肯定是正确的结果, 直接返回。
  • 另一种是内存里没有数据, 就可以肯定数据文件上是正确的结果, 读入内存后返回。这样的效率最高。

3)MySQL认为系统”空闲“的时候,只要有机会就会刷一点”脏页“。对应的是《孔乙己》生意不忙的时候, 或者打烊之后。 这时候柜台没事, 掌柜闲着也是闲着, 不如更新账本。

4)MySQL正常关闭时,会把内存的”脏页“都flush到磁盘,这样下次MySQL启动的时候, 就可以直接从磁盘上读数据, 启动速度会很快。对应的是《孔乙己》年底了咸亨酒店要关门几天, 需要把账结清一下。 这时候掌柜要把所有账都记到账本上, 这样过完年重新开张的时候, 就能就着账本明确账目情况了。

问3:上面四种场景对性能的影响如何?

1)“redo log写满了, 要flush脏页”, 这种情况是InnoDB要尽量避免的。因为出现这种情况的时候, 整个系统就不能再接受更新了, 所有的更新都必须堵住。

2)“内存不够用了, 要先将脏页写到磁盘”, 这种情况其实是常态。 InnoDB用缓冲池( buffer pool) 管理内存, 缓冲池中的内存页有三种状态:

  • 第一种是, 还没有使用的。
  • 第二种是, 使用了并且是干净页。
  • 第三种是, 使用了并且是脏页。

InnoDB的策略是尽量使用内存, 因此对于一个长时间运行的库来说, 未被使用的页面很少。而当要读入的数据页没有在内存的时候, 就必须到缓冲池中申请一个数据页。 这时候只能把最久不使用的数据页从内存中淘汰掉(LUR机制): 如果要淘汰的是一个干净页, 就直接释放出来复用。 但如果是脏页呢, 就必须将脏页先刷到磁盘, 变成干净页后才能复用。

刷脏页虽然是常态, 但是出现以下这两种情况, 都是会明显影响性能的:

  • 一个查询要淘汰的脏页个数太多, 会导致查询的响应时间明显变长。
  • 日志写满, 更新全部堵住, 写性能跌为0, 这种情况对敏感业务来说, 是不能接受的。

注1:更新数据时,更改首先发生在内存中,同时相关的更改也会被记录到redo log中(WAL)。然后,这些更改(无论是内存中的数据页还是redo log)最终都需要被刷新到磁盘上。

注2:内存中的脏页和redo log中的脏页是独立的,都需要被flush到磁盘。内存满了,刷内存中的脏页。redo log满了刷redo log中的脏页。

注3:redo log主要用于crash safe。

InnoBD刷脏页的控制策略


首先, 你要正确地告诉InnoDB所在主机的IO能力, 这样InnoDB才能知道需要全力刷脏页的时候, 可以刷多快。

这就要用到innodb_io_capacity这个参数了, 它会告诉InnoDB你的磁盘能力。 这个值我建议你设置成磁盘的IOPS。

注:测试磁盘IOPS:fio -filename=$filename -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=16k -size=500M-numjobs=10 -runtime=10 -group_reporting -name=mytest

因为没能正确地设置innodb_io_capacity参数, 而导致的性能问题也比比皆是。 之前, 就曾有其他公司的开发负责人找我看一个库的性能问题, 说MySQL的写入速度很慢, TPS很低,但是数据库主机的IO压力并不大。 经过一番排查, 发现罪魁祸首就是这个参数的设置出了问题。他的主机磁盘用的是SSD, 但是innodb_io_capacity的值设置的是300。 于是, InnoDB认为这个系统的能力就这么差, 所以刷脏页刷得特别慢, 甚至比脏页生成的速度还慢, 这样就造成了脏页累积, 影响了查询和更新性能。

问1:虽然我们现在已经定义了“全力刷脏页”的行为, 但平时总不能一直是全力刷吧? 毕竟磁盘能力不能只用来刷脏页, 还需要服务用户请求。 那么,InnoDB又是怎么控制引擎按照“全力”的百分比来刷脏页的呢?如果你来设计策略控制刷脏页的速度, 会参考哪些因素呢?

这个问题可以这么想, 如果刷太慢, 会出现什么情况? 首先是内存脏页太多, 其次是redo log写满。所以, InnoDB的刷盘速度就是要参考这两个因素: 一个是脏页比例, 一个是redo log写盘速度。

InnoDB会根据这两个因素先单独算出两个数字(F1(N)、F2(M))。然后引擎就可以按照innodb_io_capacity定义的能力乘以max(F1(N),F2(M))%来控制刷脏页的速度。

所以, 无论是你的查询语句在需要内存的时候可能要求淘汰一个脏页, 还是由于刷脏页的逻辑会占用IO资源并可能影响到了你的更新语句, 都可能是造成你从业务端感知到MySQL“抖”了一下的原因。

要尽量避免这种情况, 你就要合理地设置innodb_io_capacity的值, 并且平时要多关注脏页比例, 不要让它经常接近75%。

接下来, 我们再看一个有趣的策略。

一旦一个查询请求需要在执行过程中先flush掉一个脏页时, 这个查询就可能要比平时慢了。 而MySQL中的一个机制, 可能让你的查询会更慢: 在准备刷一个脏页的时候, 如果这个数据页旁边的数据页刚好是脏页, 就会把这个“邻居”也带着一起刷掉。 而且这个把“邻居”拖下水的逻辑还可以继续蔓延, 也就是对于每个邻居数据页, 如果跟它相邻的数据页也还是脏页的话, 也会被放到一起刷。

在InnoDB中, innodb_flush_neighbors参数就是用来控制这个行为的, 值为1的时候会有上述的“连坐”机制, 值为0时表示不找邻居, 自己刷自己的。

在MySQL 8.0中, innodb_flush_neighbors参数的默认值已经是0了。

InnoDB刷脏相关参数总结:

1)innodb_io_capacity:磁盘的io能力,推荐设置成磁盘的IOPS。

2)innodb_max_dirty_pages_pct:脏页百分比,默认75%。引擎据此以及innodb_io_capacity控制刷脏的速率。

3)innodb_flush_neighbors:刷脏时,是否连带相邻的脏页一起刷新。1表示开启。

扩展:

1)找“邻居”这个优化在机械硬盘时代是很有意义的, 可以减少很多随机IO。 机械硬盘的随机IOPS一般只有几百, 相同的逻辑操作减少随机IO就意味着系统性能的大幅度提升。

2)而如果使用的是SSD这类IOPS比较高的设备的话, 我就建议你把innodb_flush_neighbors的值设置成0。 因为这时候IOPS往往不是瓶颈, 而“只刷自己”, 就能更快地执行完必要的刷脏页操作, 减少SQL语句响应时间。

规范:一个内存配置为128GB、innodb_io_capacity设置为20000的大规格实例,建议将redo log设置成4个1GB的文件。

问2:如何判定一个页是否是脏页?

每个数据页头部有LSN,8字节,每次修改都会变大。对比这个LSN跟checkpoint 的LSN,比checkpoint小的一定是干净页。

问3:如果redo log设置过小,会导致什么问题?

每次事务提交都要写redo log, 如果设置太小, 很快就会被写满, 也就是下面这个图的状态, 这个“环”将很快被写满, write pos一直追着CP。

这时候系统不得不停止所有更新, 去推进checkpoint。

这时, 你看到的现象就是磁盘压力很小, 但是数据库出现间歇性的性能下跌。

Crash Recovery逻辑


还用前面的update语句为例进行说明,update语句的执行流程图如下所示, 图中浅色框表示是在InnoDB内部执行的, 深色框表示是在执行器中执行的。

问1:在update语句执行过程中,如果在时刻A、时刻B发生崩溃,分别会造成什么后果?

答:

1)时刻A:写入redo log 处于prepare阶段之后、写binlog之前,发生了崩溃(crash)。由于此时binlog还没写,redo log也还没提交,所以崩溃恢复的时候,这个事务会回滚。

2)时刻B:也就是binlog写完,redo log还没commit前发生crash:

  • 如果redo log里面的事务是完整的,也就是已经有了commit标识(说明binlog已写完且完整),则直接提交。
  • 如果redo log里面的事务只有完整的prepare(此时可能存在binlog不完整的情况),则判断对应的事务binlog是否存在并完整:
    • 如果binlog完整,则提交事务。
    • 否则,回滚事务。

问2:MySQL怎么直到binlog是否是完整的?

一个事务的binlog是有完整格式的:

1)statement格式的binlog, 最后会有COMMIT。

2)row格式的binlog, 最后会有一个XID event。

另外, 在MySQL 5.6.2版本以后, 还引入了binlog-checksum参数, 用来验证binlog内容的正确性。 对于binlog日志由于磁盘原因, 可能会在日志中间出错的情况, MySQL可以通过校验checksum的结果来发现。 所以, MySQL还是有办法验证事务binlog的完整性的。

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

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

相关文章

c++编程(18)——deque的模拟实现(2)容器篇

欢迎来到博主的专栏——c编程 博主ID:代码小豪 文章目录 deque的数据结构deque的构造默认构造填充构造 deque的其他操作deque的插入、删除push_back和push_frontpop_back和pop_frontclear、erase和insert操作 传送门 在上一篇中,我们已经实现了deque最核…

数据仓库和数据库有什么区别?

一、什么是数据仓库二、什么是数据库三、数据仓库和数据库有什么区别 一、什么是数据仓库 数据仓库(Data Warehouse)是一种专门用于存储和管理大量结构化数据的信息系统。它通过整合来自不同来源的数据,为企业提供统一、一致的数据视图&…

【最新鸿蒙应用开发】——鸿蒙中的“Slot插槽”?@BuilderParam

构建函数-BuilderParam 传递 UI 1. 引言 BuilderParam 该装饰器用于声明任意UI描述的一个元素,类似slot占位符。 简而言之:就是自定义组件允许外部传递 UI Entry Component struct Index {build() {Column({ space: 15 }) {SonCom() {// 直接传递进来…

论文阅读:RAM++ | Open-Set Image Tagging with Multi-Grained Text Supervision

发表时间:2023年11月16 论文地址:https://arxiv.org/pdf/2310.15200 项目地址:https://github.com/xinyu1205/recognize-anything Recognize Anything Plus Model(RAM),这是一种有效利用多粒度文本监督的开…

博通加速向Nvidia发起进攻 为何连iPhone 15都不能用“苹果智能”?

博通加速向Nvidia发起进攻 博通强调的一项优势是其 XPU 的能效。其功耗不到 600 瓦,是业内功耗最低的 AI 加速器之一。 Nvidia 的许多竞争对手都想抢占其市场主导地位。其中一个不断出现的名字是 Broadcom。仔细观察就会知道原因。其 XPU 功耗不到 600 瓦&#xff…

GPT-4并非世界模型,LeCun双手赞同!ACL力证LLM无法模拟真实世界

一直以来,支持LLM的观点之一是模型可以集成海量事实知识,作为通往「世界模拟器」的基础。虽然也有不少反对意见,但缺乏实证依据。那么,LLM能否作为世界模拟器? 最近,亚利桑那大学、微软、霍普金斯大学等机构…

飞腾银河麒麟V10安装Todesk

下载安装包 下载地址 https://www.todesk.com/linux.html 安装 yum makecache yum install libappindicator-gtk3-devel.aarch64 rpm -ivh 下载的安装包文件后台启动 service todeskd start修改配置 编辑 /opt/todesk/config/config.ini 移除自动更新临时密码 passupda…

英伟达发布Nemotron-4 340B通用模型:专为生成合成数据设计的突破性AI

引言 2023年6月14日,英伟达发布了Nemotron-4 340B通用模型,专为生成训练大语言模型的合成数据而设计。这一模型可能彻底改变训练大模型时合成数据的生成方式,标志着AI行业的一个重要里程碑。本文将详细介绍Nemotron-4 340B的各个方面&#x…

Vue43-单文件组件

一、脚手架的作用 单文件组件:xxx.vue,浏览器不能直接运行!!! 脚手架去调用webpack等第三方工具。 二、vue文件的命名规则 建议用下面的两种方式。(首字母大写!!!&#x…

CDN简介

CDN 的基本概念 CDN(Content Delivery Network),即内容分发网络。 CDN是一种分布式网络架构:它由分布在不同地理位置的服务器组成网络,这些服务器协同工作以提供内容服务。 内容分发的核心目标 确保用户能够快速、可…

Matlab自学笔记三十一:结构数组的创建、索引和预分配内存

1.概念 结构(structure array)是一种具有容器特性的数据类型,它使用称为字段的数据容器对相关数据进行分组,每个字段可以包含任何类型或大小的数据,所有元素都具有相同数量的字段和相同的字段名称。(与元胞…

Java锁之舞:性能分析与优化之路

目录 一、同步锁性能分析 (一)性能验证说明 1. 使用同步锁的代码示例 2. 不使用同步锁的代码示例 3. 结果与讨论 (二)案例初步优化分析说明 1. 使用AtomicInteger原子类尝试优化分析 2. 对AtomicInteger原子类进一步优化 …

机器学习面试-常见题目

文章目录 一、框架问题1. 监督学习和无监督学习有什么不同?2. 什么是深度学习,它与机器学习算法之间有什么联系?3. 如何评估机器学习模型的有效性?4. 如何确保模型没有过拟合?5. 什么是核技巧,有什么用处&a…

4_机械臂坐标系简介

一、坐标系的标准命名 为了规范起见,有必要给机器人和工作空间专门命名和确定专门的“标准”坐标系。 图3-27为一种典型的工况,机器人抓持某种工具,并把工具末端移动到操作者指定的位置。图3-27所示的5个坐标系就是需要命名的坐标系。这五个坐…

7z及7zip-cpp最高压缩比的免费开源压缩软件

7z介绍 7z是一种主流高效的压缩格式,它拥有极高的压缩比。在计算机科学中,7z是一种可以使用多种压缩算法进行数据压缩的档案格式。该格式最初由7-Zip实现并采用,但这种档案格式是公有的,并且7-Zip软件本身亦在GNU宽通用公共许可证…

PCIe总线-RK3588 PCIe子系统简介(八)

1.PCIe子系统 RK3588 PCIe子系统如下图所示。总共拥有5个PCIe控制器。PCIe30X4(4L)支持RC和EP模式,其他4个仅支持RC模式。ITS port 1连接PCIe30X4(4L)和PCIe30X2(2L)控制器,PCIe30X4(4L)和PCIe30X2(2L)控制器使用PCIe3.0 PIPE PHY。ITS port 0连接PCIe3…

RIP路由附加度量值(华为)

#交换设备 RIP路由附加度量值 RIP(Routing Information Protocol)路由协议中的附加度量值是指在RIP路由原来度量值的基础上所增加的额外度量值,通常以跳数来表示。这个附加度量值可以是正值,也可以是负值,用于影响路…

关于STM32上用HID HOST调鼠标数据的解析

一、前言 关于这章主要是基于我前面的那篇文章 链接: 关于怎么用Cubemx生成的USBHID设备实现读取一体的鼠标键盘设备(改进版) https://blog.csdn.net/qq_29187987/article/details/139535648?spm1001.2014.3001.5501 引用的文章的简介 引用的这篇文…

数据库概述1

数据:描述事物的符号记录称为数据; 包括数字、图片、音频等; 数据库:长期储存在计算机内有组织、可共享的大量数据的集合;数据库中的数据按照一定的数据模型组织、描述和存储,具有较小的数据冗余、较高的数…