《MySQL实战45讲》——学习笔记23 “binlogredolog 的写入机制/组提交机制“

news2024/12/24 13:48:58

本篇主要介绍数据的可靠性有关的知识,包括binlog的写入机制和redolog的写入机制,通过了解这些机制从而可以在MySQL的IO性能瓶颈上做些优化;

前文介绍了MySQL在可靠性、性能相关的概念,包括WAL技术、redolog与binlog、2阶段提交、change buffer、flush等,得到的结论是:只要redolog和binlog保证持久化到磁盘,就能确保MySQL异常重启后,数据可以恢复;

在介绍本篇内容之前,先简单回忆下这些知识点;

WAL / redolog&binglog / 2阶段提交 / change buffer / flush时机

  • WAL技术

WAL 的全称是 Write-Ahead Logging;更新数据时,先写日志再写磁盘,节省随机写磁盘的IO消耗(转成顺序写);redolog日志中记录的更新会在"一定时机"flush到磁盘;

  • redolog&binglog

是MySQL中的两套日志;

redolog只有InnoDB有而别的引擎没有,循环写,空间有限,因此不具备“归档”这功能,是物理日志(记录的是“在某个数据页上做了什么修改”);

binlog是MySQL的Server层实现的,所有引擎都可以使用,是逻辑日志(记录的是这个语句的原始逻辑),可以追加写入;

redolog具备crash-safe能力,binlog可用于归档和主从同步;

  • 2阶段提交

InnoDB先写redolog(prepare),执行器写binlog,最后InnoDB写redolog(commit);redolog的写入拆成了两个步骤:prepare和commit,这就是"两阶段提交";此过程中,redolog和binlog通过XID关联,用于数据的崩溃恢复,并保证主从数据一致;

  • change buffer

是内存中bufferpool的一部分,将更新操作缓存在 change buffer 中,在"一定时机"作用于原数据页,得到最新结果(merge);这一机制保证不用每次更新数据时都立即将磁盘中的数据页加载到内存中做更新操作,从而节省随机读磁盘的IO消耗;写多读少、写完不马上读、非唯一索引(唯一索引字段更新需先读再判断唯一性)则推荐使用;

  • flush

意思是刷脏页,将"正确"的脏页刷到磁盘,原内存页变为"干净页";除了MySQL的定时刷和关机前刷,redolog满了(会停下所有更新)或内存bufferpool满了(内存淘汰)都会触发flush;刷脏页时会消耗IO因此不能太集中,需要根据当前脏页比例和redolog写入速度来控制频率/速度;

binlog 的写入机制

由上图可知:

  • 系统为每个事务线程分配了一片binlog cache内存,共用一份binlog文件;

  • 事务执行过程中,各个事务线程先把日志写到binlog cache中,事务提交的时,再把binlog cache写到同一份binlog文件并清空binlog cache;

  • 图中write是把日志写入到文件系统的page cache内存中,所以速度比较快;图中fsync是将数据持久化到磁盘,占用磁盘的IOPS;

其中,write和fsync的时机,是由参数sync_binlog控制的:

  • sync_binlog=0,表示每次提交事务都只write,不fsync;

  • sync_binlog=1,表示每次提交事务都会执行fsync;

  • sync_binlog=N(N>1),表示每次提交事务都write,但累积N个事务后才fsync;

因此,在出现IO瓶颈的场景里,将sync_binlog设置成一个比较大的值,可以提升性能;在实际的业务场景中,考虑到丢失日志量的可控性,一般不将这个参数设成0,比较常见的是将其设置为100~1000中的某个数值;

需要注意将sync_binlog设置为N(N>1),对应的风险是:如果主机发生异常重启,会丢失最近N个事务的binlog日志

redo log 的写入机制

与binlog类似,redolog在写入过程中也会经历在redolog buffer、page cache、disk这3个阶段,并且InnoDB提供了innodb_flush_log_at_trx_commit参数,来控制redolog的写入策略:

  • 设置为0,表示每次事务提交时都只是把redolog留在redolog buffer中;

  • 设置为1,表示每次事务提交时都将redolog直接持久化到磁盘;

  • 设置为2,表示每次事务提交时都只是把redolog写到page cache;

InnoDB有一个后台线程,每隔1秒,就会把redolog buffer中的日志,调用write写到文件系统的page cache,然后调用fsync持久化到磁盘;

注意,事务执行"中间过程"的redolog也是直接写在redolog buffer中的,这些redolog也会被后台线程一起持久化到磁盘;也就是说,一个还没有提交的事务的redolog,也是有可能被持久化到磁盘的

除了后台线程每秒一次的轮询操作外,还有两种场景会让一个没有提交的事务的redolog写入到磁盘中:

  • 一种是,redolog buffer占用的空间即将达到innodb_log_buffer_size一半的时候,后台线程会主动写盘;注意,由于此时这个事务还没有提交,所以这个写盘动作只是write,而没有调用fsync,也就是只留在了文件系统的page cache。

  • 另一种是,并行的事务提交的时候,由于各个事务线程共享redolog buffer,其他事务提交,顺带将这个还未提交的事务的redolog从redolog buffer持久化到磁盘;

假设一个事务A执行到一半,已经写了一部分redolog到buffer中,这时候有另外一个线程的事务B提交,如果innodb_flush_log_at_trx_commit设置的是1,那么按照这个参数的逻辑,事务B要把redolog buffer里的日志全部持久化到磁盘;这时候,就会带上事务A在redolog buffer里的日志一起持久化到磁盘;

组提交(group commit)机制

通常我们说MySQL的“双1”配置,指的就是sync_binlog和innodb_flush_log_at_trx_commit都设置成1;也就是说,一个事务完整提交前,需要等待两次刷盘,一次是redolog(prepare阶段),一次是binlog;

这时候,你可能有一个疑问,如果从MySQL看到的TPS是每秒两万的话,每秒就会写四万次磁盘;但是,用工具测试出来,磁盘能力也就两万左右,怎么能实现两万的TPS?

解释这个问题,就要用到组提交(group commit)机制了;下面举个栗子,如图3所示,是3个并发事务(trx1,trx2,trx3)在prepare阶段,都写完redologbuffer,准备持久化到磁盘的过程,对应的LSN分别是50、120和160;

这里引入了日志逻辑序列号(log sequence number,LSN)的概念;LSN是单调递增的(有序),用来对应redolog的一个个写入点;每次写入长度为length的redolog,LSN的值就会加上length;LSN也会写到InnoDB的数据页中,来确保数据页不会被多次执行重复的redolog

由图可知,

  1. trx1是第一个到达的,会被选为这组的leader;

  1. 等trx1要开始写盘的时候,发现这个组里面已经有了3个事务,最大的LSN=160,这时候trx1的LSN也变成了160;

  1. trx1去写盘的时候,带的就是LSN=160,因此等trx1返回时,所有LSN小于等于160的redolog,都已经被持久化到磁盘;

  1. 这时候trx2和trx3就可以直接返回了;

所以,一次组提交里面,组员越多,节约磁盘IOPS的效果越好;在并发更新场景下,第一个事务写完redolog buffer以后,接下来这个fsync越晚调用,组员可能越多,节约IOPS的效果就越好

MySQL针对组提交的优化

为了让一次fsync带的组员更多,MySQL有一个很有趣的优化:拖时间——对于单个事务的提交,不急着立即fsync而是等一等

在介绍两阶段提交的时候,有下面的这一张图:

图中,"写binlog"是一个动作,但MySQL针对组提交机制做了优化,实际上,写binlog是分成两步的

  • 先把binlog从binlogcache中写到磁盘上的binlog文件;

  • 调用fsync持久化;

MySQL为了让组提交的效果更好,把redolog做fsync的时间拖到了步骤1之后;也就是说,上面的图实际变成了这样:

这么一来,binlog也可以组提交了;在执行图中第4步把binlog fsync到磁盘时,如果有多个事务的binlog已经write写完了,也是一起持久化的,这样也可以减少IOPS的消耗

现在你就能理解了,WAL机制主要得益于两个方面

  • redolog和binlog都是顺序写,磁盘的顺序写比随机写速度要快

  • 充分利用组提交机制,可以大幅度降低磁盘的IOPS消耗

下篇文章:待定

本章参考:23 | MySQL是怎么保证数据不丢的?

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

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

相关文章

阿里云图标使用 (symbol 引用方式)

阿里云图标网址: https://www.iconfont.cn/ 一、登录注册 这个简单,就不说了 二、给当前项目找图库 2.1、添加项目 2.2、寻找图标添加入库 添加入库 2.3、打开入库 的图标添加到指定项目 添加到当前项目 1 2 三、项目使用图标 ( symbol 引用方式) 3.1、下…

《HelloGitHub》第 82 期

兴趣是最好的老师,HelloGitHub 让你对编程感兴趣!简介HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。https://github.com/521xueweihan/HelloGitHub这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 Pyth…

Studio One6有哪些新功能及系统配置要求介绍

Studio One6全新版本上线记录、生产、混合、掌握和执行所有操作。从工作室到舞台,Studio One6以易用为核心,是您的创意合作伙伴。当你准备好登上舞台时,Studio One就在那里。只有Studio One从最初的灵感到完整的制作,最终混音到精…

一个数码管显示0-F

数码管的一种是半导体发光器件,数码管可分为七段数码管和八段数码管,区别在于八段数码管比七段数码管多一个用于显示小数点的发光二极管单元DP(decimal point),其基本单元是发光二极管。七段数码管是一类价格便宜使用简…

VuePress 搭建结合GitHub Pages CI

简介 VuePress 是尤雨溪(vue.js 框架作者)4月12日发布的一个全新的基于 vue 的静态网站生成器,实际上就是一个 vue 的 spa 应用,内置 webpack,可以用来写文档。详见 VuePress中文网 其实类似的建站工具有很多&#x…

Java多线程 - 创建线程池的方法 - ThreadPoolExecutor和Executors

文章目录线程池(重点)线程池介绍实现线程池的方式方式一: 实现类ThreadPoolExecutorThreadPoolExecutor构造器的参数线程池处理Runnable任务线程池处理Callable任务方式二: Executors工具类创建线程池线程池(重点) 线程池介绍 什么是线程池? 线程池就是一个可以复用线程的技…

以太网报文详解

以太网数据帧格式 以太网链路传输的数据包称做以太帧,或者以太网数据帧。在以太网中,网络访问层的软件必须把数据转换成能够通过网络适配器硬件进行传输的格式。 以太帧的工作机制 当以太网软件从网络层接收到数据报之后,需要完成如下操作&am…

模拟实现stack queue/dequeue/适配器/优先级队列/仿函数

⭐前言:学习C的STL,我们不仅仅要要求自己能够熟练地使用上层语法,我们还必须要求自己了解其底层原理,不需要了解得太深入,但一定得知道我们写出的各种代码后面,究竟采用了哪种设计思想,为什么要…

口碑巨制《流浪地球2》,再燃中国科幻电影新高度!

2019年,中国本土科幻电影《流浪地球》以炸裂之势吸引一众目光。上映26天,票房突破45亿,强势开启中国科幻电影的元年。如今时隔4年,《流浪地球2》再度登陆春节档,票房口碑双丰收,上映四天票房破13亿、淘票票…

Android渗透测试12:IDA动态调试so

0x00 前言 上一篇分享了使用 Android studio 和 Jeb 对 Apk 文件直接进行动态调试,本文将分享使用 IDA pro 调试 so 。 调试的 apk 文件还是使用 CTF案例4 的文件,已经上传到知识星球,可自行下载 本文涉及技术: IDA pro 工具使…

论文解读 - 城市自动驾驶车辆运动规划与控制技术综述 (第4部分)

文章目录🚗 IV. Mothon Planning(运动规划)🟢 D. Graph Search Methods(图搜索算法)🟥 1) Lane Graph(车道图)🟧 2) Geometric Methods(几何方法&…

AtCoder Beginner Contest 287 A-G 赛时思路+正解

一把给我加到1219了,青大小蒟蒻表示很开心。 A - Majority 题意 问你"For""For""For"字符串数量是否比"Against""Against""Against"数量多。 思路 mapmapmap暴力即可。 A题代码 B - Postal Card 题意…

电脑技巧:教你关闭Win11内存压缩,解决电脑卡顿的问题

很多朋友都注意到,Win11默认开启了内存压缩功能。内存压缩顾名思义,可以压缩内存中的数据,让内存占用更少,同时减少Swap频次,带来更高的I/O效率。 但与此同时,压缩数据需要耗费CPU资源,一些朋友…

Dr4g0n-b4ll靶机总结

Dr4g0n-b4ll靶机渗透测试总结 靶机下载地址: https://download.vulnhub.com/dr4g0nb4ll/Dr4g0n-b4ll.zip 打开靶机,使用nmap扫描靶机的ip和所有开放的端口 可以看到靶机开放了80端口和22端口 根据80端口打开网站 信息收集,目录爆破 在robots.txt下发现一串base64编码 eW91IG…

编写循环(RH294)

循环这东西你早就懂的不是么就像python里的for一样在ansible中 使用loop关键字来实现迭代简单循环简单循环中一般使用loop关键字来开始循环使用循环变量item来存储每个迭代过程中使用的值举个例子 栗子啊首先让我们拿出两个任务片段- name: Postfix is runningservice:name: po…

索引15连问

前言 大家好,我是田螺。 金三银四很快就要来啦,准备了索引的15连问,相信大家看完肯定会有帮助的。 公众号:捡田螺的小男孩 1. 索引是什么? 索引是一种能提高数据库查询效率的数据结构。它可以比作一本字典的目录&am…

从C语言的使用转换到C++(下篇)——刷题、竞赛篇

目录 一、CSTL的简介 二、STL的使用详解 2、1 STL之动态数组vector的使用 2、2 STL之集合set的使用 2、3 STL之映射map的使用 2、4 STL之栈stack的使用 2、5 STL之队列queue的使用 2、6 STL之unordered_map和unordered_set的使用 三、总结 标题:从C语言的使用转换…

还不会SpringBoot项目模块分层?来这手把手教你

文章目录前言🍊缘由⏲️本文阅读时长🎯主要目标👨‍🎓试用人群🎁快速链接🍩水图正文🥫1.IDEA新建项目🌭2.创建子模块-dependencies(依赖层)🎯重点🍪3.创建子模…

【寒假小练】day2

前言 日积跬步&#xff0c;能至千里。 水平有限&#xff0c;不足之处望请斧正。 选择题 1、以下程序运行后的输出结果是( ) #include <stdio.h> void fun(char **p) {int i;for(i 0; i < 4; i) {printf("%s", p[i]); } int main() {char *s[6] {"…

Python 本地django外部网络访问

目录 一、前提 1、确定在本地可以访问 二、 本地django项目外部网络访问 1、在settings中配置允许所有服务器访问&#xff08;局域网访问&#xff09; 2、Host配置 3、使用内网穿透工具&#xff08;ngrok&#xff09;&#xff08;外部网络访问&#xff09; &#xff08;…