MySQL日志(二):MySQL抖动

news2024/10/6 12:23:57

一条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.coloradmin.cn/o/1826919.html

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

相关文章

FreeRTOS简单内核实现3 任务管理

文章目录 0、思考与回答0.1、思考一0.2、思考二0.3、思考三 1、任务控制块2、创建任务2.1、xTaskCreateStatic( )2.2、prvInitialiseNewTask( )2.3、pxPortInitialiseStack( )2.4、任务内存详解 3、就绪链表3.1、定义3.2、prvInitialiseTaskLists( ) 4、任务调度器4.1、vTaskSt…

阿里云系列产品免费用,不香吗?

阿里云系列产品免费用,不香吗? 什么是无影云电脑开启无影云下载安装客户端登录无影云桌面应用场景 开篇先发布一下阿里云产品免费体验地址:https://free.aliyun.com/?utm_contentg_1000370296 下面开始我的无影云电脑或者叫做无影云桌面的体…

LLM大语言模型算法特训,带你转型AI大语言模型算法工程师(完结)

LLM大语言模型算法 与AI大语言模型算法工程师的联系 LLM(Large Language Model)大语言模型是指像GPT这样的大型自然语言处理模型,而AI大语言模型算法工程师则是负责开发和优化这些模型的专业人士。它们之间的联系可以从以下几个方面来理解&a…

linux驱动学习(十二)之看门狗

一、看门狗定时器功能 1、产生复位信号:当系统受到由于噪声或者干扰而造成系统死机,看门狗产生一个复位信号。 2、普通定时器:16bits定时器,产生周期性的中断信号 二、看门狗系统框图 设置计数值以每隔10S就会产生一个复位信号&…

springboot依赖管理和自动配置

依赖管理和自动配置 依赖管理和自动配置依赖管理什么是依赖管理修改自动仲裁/默认版本号 starter场景启动器starter场景启动器基本介绍官方提供的starter第三方starter 自动配置自动配置基本介绍SpringBoot自动配置了哪些?如何修改默认配置如何修改默认扫描包结构resources\ap…

STM32学习笔记(一)--时钟树详解

(1)时钟概述;时钟是具有周期性的脉冲信号,最常用的是占空比50%的方波。(时钟相当于单片机的脉搏;STM32本身非常复杂,外设非常的多,为了保持低功耗工作,STM32 的主控默认不…

亿达中国武汉园区入选“武汉市科技金融工作站”及“武汉市线下首贷服务站”

近日,武汉市2024科技金融早春行活动在深交所湖北资本市场培育基地举行。会上,第四批武汉市科技金融工作站试点单位名单及第五批武汉地区金融系统线下首贷服务站名单正式公布,武汉软件新城成功入选上述两个名单。 为缓解科技型企业融资难题&a…

远程问诊软件哪款好?选欣九康诊疗系统

近几年国家相继推出了支持发展“互联网医疗”的政策,如今随着相关政策的不断落实推进,市场上涌现出了一大批在线咨询、电子处方和远程问诊的医疗平台,而在面对种类如此繁多的医疗平台究竟选择哪款更好便成了医疗机构非常头疼的事情&#xff0…

【源码】综合股票币币合约交易所源码/etf交易所源码/美股港股台股交易所源码

支持多国语言 全开源可二开的一个版本!支持虚拟货币 ETF 外汇 美股 A股 港股 台股。 前端是VUE开发(带vue工程源码)后端JAVA开发!搭建也相对简单。 总的来说功能非常强大,适合线上运营的一个版本,有兴趣的可…

RabbitMQ无法删除unsynchronized队列及解决办法

一、故障环境 操作系统:CentOS7 RabbitMQ:3 nodes Cluster RabbitMQ version: 3.8.12 Erlang Version:22.3 Queue Type:Mirror,with polices 二、故障表现: 2.1 管理界面队列列表中存在部分队列镜像同步状态标红: 2.2 TPS为0,无消费者,其他节点镜像未同步且无法手动…

【SpringBoot】Spring Boot 中高级特性详解

文章目录 1. 异步处理1.1 什么是异步处理?1.2 实现异步处理1.2.1 启用异步支持1.2.2 使用 Async 注解1.2.3 调用异步方法 2. 安全管理2.1 Spring Security 集成2.2 基础安全配置2.2.1 添加依赖2.2.2 默认配置2.2.3 自定义用户认证 3. 监控和调试3.1 Spring Boot Act…

结构体对齐,与 触发 segment fault 为什么是 1024*132 ,而不是1024*128

1, 简单的小示例代码 按理说 malloc 的size 是 1024*128&#xff0c;这里却需要 1024*132才能及时触发 segmentation fault #include <stdlib.h> #include <stdio.h> #define SIZE 1024*131int main() {char *p 0;p malloc(SIZE);p[SIZE -1] a;free(p);printf(…

WWDC 2024 回顾:Apple Intelligence 的发布与解析

一年一度的苹果全球开发者大会&#xff08;WWDC&#xff09;如期而至&#xff0c;2024 年的 WWDC 再次成为科技界的焦点。本次发布会中&#xff0c;苹果正式推出了他们在 AI 领域的全新战略——Apple Intelligence。这一全新概念旨在为用户打造“强大、易用、全面、个性化、注重…

正运动邀您共聚2024深圳激光展,助力激光加工与智能制造!

■展会名称 2024深圳激光展 ■展会日期 2024年6月19日 - 21日 ■展馆地点 深圳国际会展中心&#xff08;新馆&#xff09; ■展位号 9H - D101 6月19至21日&#xff0c;深圳激光展将在中国深圳国际会展中心(新馆)举办。 激光加工在消费电子、光伏锂电新能源、半导体等行…

展厅设计要关注的基本点

1、设计方案 每个企业都会有不同的风格特色&#xff0c;找到一个合适企业的设计方案才是重点&#xff0c;所以在策划设计上要有一套个性化的方案。大到展厅内的结构&#xff0c;小到单个的展陈框架摆放&#xff0c;都要有详细的规划&#xff0c;这样才能够打造出一个效果突出的…

深度学习笔记: 最详尽估算送达时间系统设计

欢迎收藏Star我的Machine Learning Blog:https://github.com/purepisces/Wenqing-Machine_Learning_Blog。如果收藏star, 有问题可以随时与我交流, 谢谢大家&#xff01; 估算送达时间 1. 问题陈述 构建一个模型来估算在给定订单详情、市场条件和交通状况下的总送达时间。 为…

探索Docker容器网络

Docker容器已经成为现代应用部署的核心工具。理解Docker的网络模型对于实现高效、安全的容器化应用至关重要。在这篇博客中&#xff0c;我们将深入探讨Docker的网络架构&#xff0c;并通过一些代码例子来揭示其底层实现。 Docker网络模式 Docker提供了多种网络模式&#xff0c…

大模型系列:C-Eval中文大模型评测数据集介绍和实践

前言 C-Eval是目前权威的中文AI大模型评测数据集之一&#xff0c;用于考察大模型的知识和推理能力&#xff0c;本篇对C-Eval数据集做简要介绍&#xff0c;并演示如何使用C-Eval对大模型进行评测。 内容摘要 C-Eval整体结构概述C-Eval数据预览C-Eval的Prompt范式Python脚本实现…

第九十一周周报

学习目标&#xff1a; 论文 学习时间&#xff1a; 2024.6.8-2024.6.14 学习产出&#xff1a; 一、Consistency Models 扩散模型依赖于迭代采样过程导致生成缓慢&#xff0c;由此提出一致性模型&#xff0c;其可以直接将噪声映射至数据从而生成高质量样别。 根据给定的OD…

Kotlin编程实践-【Java如何调用Kotlin中带默认值参数的函数】

问题 如果你有一个带有默认参数值的 Kotlin 函数&#xff0c;如何从 Java 调用它而无须为每个参数显式指定值&#xff1f; 方案 为函数添加注解JvmOverloads。 也就是为Java添加重载方法&#xff0c;这样Java调用Kotlin的方法时就不用传递全部的参数了。 示例 在 Kotlin …