MySQL-三大日志

前言

redo log:为了持久化数据,当内存中的数据还没写入到磁盘而宕机时,会读取该日志持久化数据到磁盘

undo log:为了保证原子性,事务的操作都会记录一条相反的sql到该日志,出现错误就会根据该文件恢复事务之前的数据

binlog:为了复制和恢复数据,mysql重启可以通过该日志恢复

​ 以上三大日志是MySQL的原子性、持久性、数据一致性的保证。

bin log

bin log全称binary log,二进制日志文件,它记录了数据库所有执行的 DDLDML 等数据库更新的语句,但是不包含select或者show等没有修改任何数据的语句。它是MySQL级别的日志,也就是说所有的存储引擎都会产生bin log,而redo log或者undo log事务日志只有innoDB存储引擎才有。

可以使用show binary logs; 命令查看所有二进制日志列表。可以看到binlog 日志文件名为 文件名.00000 形式。*

​ 通过 show binlog events in ‘binlog.000008’ limit 10; 命令查看日志的具体内容。另外一定要指定 limit,不然查询出来的日志文件内容太多。另外, MySQL 内置了 binlog 查看工具 mysqlbinlog,可以解析二进制文件。

1、写入方式

​ binlog 通过追加的方式进行写入,大小没有限制。另外可以通过max_binlog_size参数设置每个 binlog 文件的最大容量,当文件大小达到给定值之后,会生成新的 binlog 文件来保存日志,不会出现前面写的日志被覆盖的情况。

写入流程

1)为了保证写的效率,会将事务的bin log先写到binlog cache中,这个cache位于事务线程的内存中,主要是一个事务的bin log不能被拆开,是一个整体。

**2)在提交事务的时候,将binlog cache中的数据统一写到文件系统缓存page cache中,**这个过程速度也很快

3)然后根据不同的策略,将文件系统缓存中的bin logfsync刷到磁盘中,这里的策略后面详细讲解。

2、3种binlog 的格式

1)Statement 模式 :每一条会修改数据的sql都会被记录在binlog中,如inserts, updates, deletes。
**2)Row 模式 (推荐): 为了解决Statement缺点,记录具体哪一个分区中的、哪一个页中的、哪一行数据被修改了。**但是适用于数据量比较大的场景,否则记录分区信息,查找规则,磁盘IO、网络带宽开销很大。

3)Mixed 模式 :Statement 模式和 Row 模式的混合。

​ **默认使用 Statement 模式,少数特殊具体场景自动切换到 Row 模式。**MySQL 5.1.5 之前 binlog 的格式只有 STATEMENT,5.1.5 开始支持 ROW 格式的 binlog,从 5.1.8 版本开始,MySQL 开始支持 MIXED 格式的 binlog。MySQL 5.7.7 之前,默认使用 Statement 模式。MySQL 5.7.7 开始默认使用 Row 模式。

相比较于 Row 模式来说,Statement 模式下的日志文件更小,磁盘 IO 压力也较小,性能更好有些。不过其准确性相比于 Row 模式要差。可以使用 show variables like ‘%binlog_format%’; 查看 binlog 使用的格式。

3、应用场景

binlog 最主要的应用场景是 主从复制和数据恢复 ,主从复制常见是主备、主主、主从都离不开binlog,需要依靠 binlog 来同步数据,保证数据一致性。

​ 可以使用show variables like ‘log_bin’;查看数据库是否启用 binlog 日志,默认是开启的。

1)主从复制的原理:
  • 主库将数据库中数据的变化写入到 binlog
  • 从库连接主库
  • 从库会创建一个 I/O 线程向主库请求更新的 binlog
  • 主库会创建一个 binlog dump 线程来发送 binlog ,从库中的 I/O 线程负责接收
  • 从库的 I/O 线程将接收的 binlog 写入到 relay log 中。
  • 从库的 SQL 线程读取 relay log 同步数据本地(也就是再执行一遍 SQL )。
2)Canal主从复制原理;
  • Canal 模拟 MySQL Slave 节点与 MySQL Master 节点的交互协议,把自己伪装成一个 MySQL Slave 节点,向 MySQL Master 节点请求 binlog;
  • MySQL Master 节点接收到请求之后,根据偏移量将新的 binlog 发送给 MySQL Slave 节点;
  • Canal 接收到 binlog 之后,就可以对这部分日志进行解析,获取主库的结构及数据变更。

4、binlog 的刷盘时机

​ **对于InnoDB存储引擎而言,事务在执行过程中,会先把日志写入到binlog cache中,只有在事务提交的时候,才会把binlog cache中的日志持久化到磁盘上的binlog文件中。**写入内存的速度更快,这样做也是为了效率考虑。

因为一个事务的binlog不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache。我们可以通过binlog_cache_size参数控制单个线程 binlog cache 大小,如果存储内容超过了这个参数,就要暂存到磁盘(Swap)。

刷盘策略

biglog有3种刷盘策略, bin log的write和fsync时机是由参数 sync_binlog 控制。 MySQL5.7 之前, sync_binlog 默认值为 0。在 MySQL5.7 之后, sync_binlog默认值为 1。

  • 0:不去强制要求。

​ 表示每次提交事务都只 write,由系统自行判断什么时候执行fsync。虽然性能得到提升,但是机器宕机,page cache里面的 binglog 会丢失。

  • 1:每次提交事务的时候都要将binlog写入磁盘,也就是说都会执行fsync
  • N:每 N 个事务,才会将binlog写入磁盘(累积N个事务后才fsync)。

什么情况下会重新生成 binlog?

●MySQL服务器停止或重启;

●使用 flush logs 命令后;

●binlog 文件大小超过 max_binlog_size变量的阈值后。

bin log没写完,bin log 与redo log之间的一致性问题有什么解决方案?

​ InnoDB存储引擎使用两阶段提交方案。将redo log的写入拆成了两个步骤preparecommit

​ 假如现在写入bin log时MySQL发生异常,这时候的redo log还处于prepare阶段,重启MySQL后,根据redo log记录中的事务ID,发现没有对应的bin log日志,回滚前面已写入的数据。

​ 如果redo logcommit阶段发生移除,但是能通过事务id找到对应的bin log日志,所以MySQL认为是完整的,就会提交事务恢复数据。

数据恢复?

通过使用 mysqlbinlog 工具来恢复数据。

redo log

MySQL InnoDB 引擎使用 redo log 来保证事务的持久性。redo log 主要做的事情就是记录页的修改,比如某个页面某个偏移量处修改了几个字节的值以及具体被修改的内容是什么。redo log 中的每一条记录包含了表空间号、数据页号、偏移量、具体修改的数据,甚至还可能会记录修改数据的长度(取决于 redo log 类型)。

redo log包含两部分:内存中的日志缓冲(redo log buffer)和磁盘上的日志文件(redo logfile)。内存层面,默认16M,通过innodb_log_buffer_size参数可修改。

​ MySQL 每执行一条 DML 语句,先将记录写入 redo log buffer,后续某个时间点再一次性将多个操作记录写到 redo log file。

写入过程

在计算机操作系统中,用户空间( user space )下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间( kernel space )缓冲区( OS Buffer )。因此, redo log buffer 写入 redo logfile 实际上是先写入 OS Buffer ,然后再通过系统调用 fsync() 将其刷到 redo log file中。

流程:
  • 先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝,产生脏数据
  • 生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值
  • 默认在事务提交后将redo log buffer中的内容刷新到redo log file,对redo log file采用追加写的方式
  • 定期将内存中修改的数据刷新到磁盘中(这里指的是内存缓冲池中的脏页 )

写入策略

当redo log空间满了之后又会从头开始以循环的方式进行覆盖式的写入。MySQL 支持三种将 redo log buffer 写入 redo log file 的时机,可以通过 innodb_flush_log_at_trx_commit 参数配置,各参数含义如下:

  • 0(延迟写):表示每次事务提交时都只是把 redo log 留在 redo log buffer 中,开启一个后台线程,每1s刷新一次到磁盘中 ;
  • 1(实时写,实时刷):表示每次事务提交时都将 redo log 直接持久化到磁盘,真正保证数据的持久性;
  • 2(实时写,延迟刷):表示每次事务提交时都只是把 redo log 写到 page cache,具体的刷盘时机不确定。

​ 除了上面几种机制外,还有其它两种情况会把redo log buffer中的日志刷到磁盘。

  • 定时处理:有线程会定时(每隔 1 秒)把redo log buffer中的数据刷盘。
  • 根据空间处理:redo log buffer 占用到了一定程度( innodb_log_buffer_size 设置的值一半)占,这个时候也会把redo log buffer中的数据刷盘。

重做日志缓冲(redo log)

重做日志(redo log)是数据库的重要组成,他保证了数据库宕机并重启后数据恢复的正确性。重做日志共有两个文件ib_logfile0和ib_logfile1。每个文件的大小一直且循环写入,也就是说先写ib_logfile0,写满之后再写ib_logfile1,又写满后,继续写ib_logfile0。

​ **redo log日志里面记录的主要是:表空间+数据页号+偏移量+修改几个字节的值+具体的值。**根据你修改了数据页里的几个字节的值,redo log就划分为了不同的类型,MLOG_1BYTE类型的日志指的就是修改了1个字节的值,MLOG_2BYTE类型的日志指的就是修改了2个字节的值,以此类推,还有修改了4个字节的值的日志类型,修改了8个字节的日志类型。如果修改了一大串的值,类型就是:MLOG_WRITE_STRING,就是代表你一下子在哪个数据页的某个偏移量的位置插入或者修改了一大串的值。

所以redo log看起来的结构如下:日志类型(类似MLOG_1BYTE之类的数据),表空间ID,数据页号,数据页中的偏移量,修改数据长度(MLOG_WRITE_STRING类型的才有),具体修改的数据。

当数据库修改页时,会将修改信息放入重做日志缓冲区,然后按一定频率(默认每秒一次)写入到重做日志文件,重做日志缓冲区一般不需要设置很大,只要保证每秒产生的事务量在这个缓冲区大小内即可,缓冲区大小可以通过参数innodb_log_buffer_size配置,默认为8MB

写入触发

​ 一般情况下,对于通常的事务提交,分为三个阶段:

  • 事务准备提交:
  • 事务提交过程中:
  • 事务提交完成:

​ **主要过程是,在事务提交时候, 会发生强制的将 redo log buffer的日志缓存的数据,强制写入 redo log file中, 通常会调用一次操作系统的fsync()的操作。**其中还会经过操作系统的内核空间, OS buffer ,因为MySQL的进行和日志缓存都工作在操作系统中环境下

本质:

事务提交的过程中,必须将日志缓存的数据持久化到磁盘的日志文件中,期间还需要经过操作系统的 “内核空间缓存区”,也就是OS Buffer区域,Redo log从用户空间的 Log buffer 写入磁盘的Redo Log文件时,需要要内核空间的OS buffer;日志文件,没有使用 O_DIRECT标识,如果有这个标识,就可以不经过这个os buffer的内核空间,直接写入磁盘数据;

问题

1)为什么不直接修改磁盘中的数据?

​ 因为直接修改磁盘数据的话,它是随机IO,修改的数据分布在磁盘中不同的位置,需要来回的查找,所以命中率低,消耗大,而且一个小小的修改就不得不将整个页刷新到磁盘,利用率低;

与之相对的是顺序IO,磁盘的数据分布在磁盘的一块,所以省去了查找的过程,节省寻道时间。使用后台线程以一定的频率去刷新磁盘可以降低随机IO的频率,增加吞吐量,这是使用buffer pool的根本原因。

2)redo log一定能保证事务的持久性吗?

​ 不一定,这要根据redo log的刷盘策略决定,因为redo log buffer同样是在内存中,如果提交事务之后,redo log buffer还没来得及将数据刷新到redo log file进行持久化,此时发生宕机照样会丢失数据。

​ 刷盘写入策略。

3)页修改之后为什么不直接刷盘呢?

​ InnoDB 页的大小一般为 16KB,而页又是磁盘和内存交互的基本单位。这就导致即使我们只修改了页中的几个字节数据,一次刷盘操作也需要将 16KB 大小的页整个都刷新到磁盘中。而且,这些修改的页可能并不相邻,也就是说这还是随机 IO。

采用 redo log 的方式就可以避免这种性能问题,因为 redo log 的刷盘性能很好。首先,redo log 的写入属于顺序 IO。 其次,一行 redo log 记录只占几十个字节。另外,Buffer Pool 中的页(脏页)在某些情况下(比如 redo log 快写满了)也会进行刷盘操作。不过这里的刷盘操作会合并写入,更高效地顺序写入到磁盘。

4)什么情况下会将缓冲区内容写入到重做日志中

1)主线程Master Thread每秒会写入一次

2)每个事务提交时会写入一次

3)当重做日志缓冲池剩余空间小于50%时,会写入一次

undo log

undo log也属于引擎层(innodb)的日志,由上可知,redo log 和undo log的核心是为了保证innodb事务机制中的持久性和原子性,事务提交成功由redo log保证数据持久性,而事务可以进行回滚从而保证事务操作原子性则是通过undo log 来保证的。

应用场景

1)事务回滚

​ 后台线程会不定时的去刷新buffer pool中的数据到磁盘,但是如果该事务执行期间出现各种错误(宕机)或者执行rollback语句,那么前面刷进去的操作都是需要回滚的,保证原子性,undo log就是提供事务回滚的。

2)MVCC

​ **在内部实现中,InnoDB 通过数据行的 DB_TRX_ID 事务ID 和 Read View 来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR 回滚指针 找到 undo log 的日志版本链做比较,即遍历链表中的事务ID,直到找到满足条件的DBTRXID,这个DBTRXID所在的旧记录就是当前事务能看到的最新老版本数据。**从中分析出该行记录以前的数据版本是怎样的,从而让用户能够读取到当前事务操作之前的数据——快照读。

MVCC 的实现依赖于:隐藏字段(自增ID、事务ID、回滚指针)、Read View、undo log。

undo log 数据格式

undo log 数据主要分两类:

1)insert undo log

insert 操作的记录,只对事务本身可见,对其他事务不可见(这是事务隔离性的要求),故该insert undo log可以在事务提交后直接删除,不需要进行purge操作。

2)update undo log

update undo log记录的是对delete和update操作产生的undo log。该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行最后的删除。

在InnoDB存储引擎中,undo log使用rollback segment回滚段进行存储,每个回滚段包含了1024个undo log segment。MySQL5.5之后,一共有128个回滚段。即总共可以记录128 * 1024个undo操作。

问题

1)undo log 如何保证事务的原子性?

​ 每一个事务对数据的修改都会被记录到 undo log ,当执行事务过程中出现错误或者需要执行回滚操作的话,MySQL 可以利用 undo log 将数据恢复到事务开始之前的状态。undo log 属于逻辑日志,记录的是 SQL 语句,比如说事务执行一条 DELETE 语句,那 undo log 就会记录一条相对应的 INSERT 语句。

2)除了保证事务的原子性,undo log 还有什么用?

InnoDB存储引擎中 MVCC 的实现用到了 undo log 。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo log读取之前的行版本信息,以此实现非锁定读取。

总结

binlog 是MySQL server层的日志,而redo log 和undo log都是引擎层(InnoDB)的日志,要换其他数据引擎那么就未必有redo log和undo log了。

它的设计目标是支持innodb的“事务”的特性,事务ACID特性分别是原子性、一致性、隔离性、持久性, 一致性是事务的最终追求的目标。隔离性是通过MVCC+锁机制来实现的,而事务的原子性和持久性则是通过redo log 和undo log来保障的。

​ redo log让InnoDB有了崩溃恢复的能力,binlog保证了MySQL集群架构的数据一致性。

​ 在执行更新语句过程,会记录redo log与binlog两块日志,以基本的事务为单位,redo log在事务执行过程中可以不断写入,而binlog只有在提交事务时才写入,所以redo log与binlog的写入时机不一样。

MySQL 三大日志中,bin log属于Server的,有缓冲buffer,缓冲区域在事务线程的内存中。redo log undo log 属于innoDB存储引擎,有缓冲buffer,在内存缓冲区域,由 LRU 链表和 Flush 链表管理。undo log 存储在引擎内部采用rollback segment回滚段进行存储。

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

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

相关文章

365天搞定八股文——Day 005 MQ中的重要概念

优先级队列:优先级高的消息有优先被消费的特权,该模式只有在生产效率高于消费效率的时候才有效果延迟队列:生产者生产完消息后,不能马上进行消费死信队列:某些消息无法被正常地消费,所以就没有办法被确认&a…

栈和队列1——栈的实现及其oj(括号匹配问题)

一,栈的概念 栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。 压栈&#xf…

【lesson7】git的介绍及使用

文章目录 什么是gitgit的历史git使用在gitee上创建仓库git clone HTTPS地址git add .git add 文件名git commit “日志”git pushgit loggit rm 文件名git statusgit pull 什么是git git是版本控制器,那么什么是版本控制器呢? 下面讲个故事为大家讲解一…

【SpringBoot】90、SpringBoot中@Value(“${...}“)的使用细节

@Value 注解可以用来将外部的值动态注入到 Bean 中,在 @Value 注解中,可以使${} 与 #{} ,它们的区别如下: @Value(“${}”):可以获取对应属性文件中定义的属性值。@Value(“#{}”):表示 SpEl 表达式通常用来获取 bean 的属性,或者调用 bean 的某个方法。根据注入的内容来…

SpringBoot开发实战(微课视频版)

ISBN: 978-7-302-52819-7 编著:吴胜 页数:311页 阅读时间:2023-06-24 推荐指数:★★★★☆ 本文介绍SpringBoot 2.0.5 、JDK 1.8,虽然现在已经不维护了,但是大体的流程还是对口的, 而且书里面讲…

Vite + Vue3 实现前端项目工程化

通过官方脚手架初始化项目 第一种方式,这是使用vite命令创建,这种方式除了可以创建vue项目,还可以创建其他类型的项目,比如react项目 npm init vitelatest 第二种方式,这种方式是vite专门为vue做的配置,…

【算法】滑动窗口破解长度最小子数组

Problem: 209. 长度最小的子数组 文章目录 题意分析算法原理讲解暴力枚举O(N^2)利用单调性,滑动窗口求解 复杂度Code 题意分析 首先来分析一下本题的题目意思 题目中会给到一个数组,我们的目的是找出在这个数组中 长度最小的【连续】子数组,而…

c++加速方法大全

我们平常写代码的时候,经常超时,非常难受,所以,我写了这篇文章,让你的代码提升速度(这些方法作者亲测有效,用了这些方法,足足提升了1秒!虽然最后题目还是没过&#xff09…

JVM 篇

目录 一、知识点汇总 二、知识点详解 2.1 JVM 的主要组成部分及其作用 2.2 JVM内存模型 2.3 堆与栈的区别 2.4 JVM 加载 class 文件的原理机制 2.5 类的生命周期 2.6 Java 对象结构 2.7 Java 对象创建过程 2.8 指针碰撞 2.9 空闲列表 2.10 TLABCAS 2.11 说…

蓝牙电话之HFP—电话音频

1 媒体音频: 播放蓝牙音乐的数据,这种音频对质量要求高,数据发送有重传机制,从而以l2cap的数据形式走ACL链路。编码方式有:SBC、AAC、APTX、APTX_HD、LDAC这五种编码方式,最基础的编码方式是SBC&#xff0…

Mysql 三级等保安全加固

安全加固的前提是保障业务稳定运行,而不是为了安全加固而加固! 1. 新增审计账号并赋予相关权限 进入数据库操作后台: mysql -h 192.168.101.17-u root -p查看数据库用户和口令信息: select host,user,plugin,authentication_string from mysql.user;查看用户权限: show …

什么是多态,instanceof,类型转换

多态 即同一个方法可以根据发送对象的不同而采用多种不同的行为方式一个对象的实际类型是确定的,按可以指向对象的引用类型有很多多态存在的条件: 有继承关系子类重写父类的方法父类引用指向子类对象 注意:多态是方法的多态,属性…

【Vue入门】语法 —— 事件处理器、自定义组件、组件通信

目录 一、事件处理器 1.1 样式绑定 1.2 事件修饰符 1.3 按键修饰符 1.4 常用控制符 1.4.1 常用字符综合案例 1.4.2 修饰符 二、自定义组件 2.1 组件介绍及定义 2.2 组件通信 2.2.1 组件传参(父 -> 子) 2.2.1 组件传参(子 ->…

Goland设置头注释

package ${GO_PACKAGE_NAME} * Author: 坐公交也用券 * HomePage: https://liumou.site * File: ${NAME}.go * Date: ${DATE} ${TIME} * Des: 文件作用

什么是AES加密?详解AES加密算法原理流程

在密码学中,加密算法分为双向加密和单向加密。单向加密包括MD5、SHA等摘要算法,它们是不可逆的。双向加密包括对称加密和非对称加密,对称加密包括AES加密、DES加密等。双向加密是可逆的,存在密文的密钥。AES算法是DES算法的替代者…

Linux 操作技巧

目录 一、shell-命令解释器 二、Linux中的特殊符号 三、命令历史--history 一、shell-命令解释器 shell——壳,命令解释器,负责解析用户输入的命令 ——内置命令(shell内置) ——外置命令,在文件系统的某个目录下&…

数据库中的DDL与DML

标签:数据库 记录下DDL和DML的相关概念。 数据定义语言 定义数据库模式 数据定义语言DDL(Data-Definition Language)可定义数据库模式。数据库模式在之前的文章中已经提到过了。简单来说,建表用的SQL语句就是DDL。如下代码 CREATE TABLE department(de…

3、靶场——Pinkys-Place v3(3)

文章目录 一、获取flag41.1 关于SUID提权1.2 通过端口转发获取setuid文件1.3 运行pinksecd文件1.4 利用nm对文件进行分析1.5 构建payload1.6 Fire 二、获取flag52.1 生成ssh公钥2.2 免密登录ssh2.3 以pinksecmanagement的身份进行信息收集2.4 测试程序/usr/local/bin/PSMCCLI2.…

安装MySQL

要安装MySQL,您可以按照以下步骤进行操作。这里将介绍如何在Linux上安装MySQL。请注意,这只是一个基本的示例,具体步骤可能会因您的操作系统和版本而有所不同。 在Ubuntu上安装MySQL: 打开终端。 更新包列表以确保获取最新的软件包信息&…