资讯专栏INFORMATION COLUMN

MySQL日志-binlog/redo log/undo log什么区别

社区管理员 / 486人阅读

一、前言

  • MySQL 整体来看,其实就有两块:一块是Server层,它主要做的是MySQL功能层面的事情;还有一块是引擎层,负责存储相关的具体事宜。

  • redo log 是 InnoDB 引擎特有的日志,而 Server 层也有自己的日志,称为 binlog(归档日志)。

二、Redo log

 WAL技术的全称是 Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。

  • 当有一条记录需要更新的时候,InnoDB引擎就会先把记录写到redo log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。

  • InnoDB 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是1GB,那么redo log总共就可以记录 4GB 的操作。从头开始写,写到末尾就又回到开头循环写。

  • image.png

  • write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到0号文件开头。checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

  • write pos和checkpoint之间的是“粉板”上还空着的部分,可以用来记录新的操作。如果write pos追上checkpoint,表示“粉板”满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推进一下。

  • 有了 redo log,InnoDB就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。

三、Binlog

3.1 为什要有binlog还需要redo log呢?

因为最开始 MySQL 里并没有 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统,也就是 redo log 来实现 crash-safe 能力。

3.2 Binlog和Redo log区别?

  • redo log 是InnoDB 引擎特有的;binlog是MySQL的Server 层实现的,所有引擎都可以使用。

  • redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2这一行的 c 字段加 1 ”。

  • redo log 是循环写的,空间固定会用完;binlog是可以追加写入的。“追加写”是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

四、Undo log

4.1 什么是多版本并发控制(MVCC)?

可重复读为例:在 MySQL 中,实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值。

假设一个值从1被按顺序改成了2、3、4,在回滚日志里面就会有类似下面的记录。

image.png

当前值是 4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的read-view。如图中看到的,在视图A、B、C里面,这一个记录的值分别是1、2、4,同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)。对于 read-view A,要得到1,就必须将当前值依次执行图中所有的回滚操作得到。

  • 同时你会发现,即使现在有另外一个事务正在将 4 改成 5,这个事务跟 read-viewA、B、C对应的事务是不会冲突的。

  • 系统会判断,当没有事务再需要用到这些回滚日志时,回滚日志会被删除。即系统里没有比这个回滚日志更早的read-view 的时候。

4.2 什么是undo log?

  • InnoDB 里面每个事务有一个唯一的事务 ID,叫作 transaction id。它是在事务开始的时候向 InnoDB 的事务系统申请的,是按申请顺序严格递增的。

  • 而每行数据也都是有多个版本的。每次事务更新数据的时候,都会生成一个新的数据版本,并且把 transaction id 赋值给这个数据版本的事务 ID,记为 row trx_id。同时,旧的数据版本要保留,并且在新的数据版本中,能够有信息可以直接拿到它。

  • 也就是说,数据表中的一行记录,其实可能有多个版本 (row),每个版本有自己的 row trx_id。

如图 所示,就是一个记录被多个事务连续更新后的状态:图中虚线框里是同一行数据的 4 个版本,当前最新版本是 V4,k 的值是 22,它是被 transaction id 为 25 的事务更新的,因此它的 row trx_id 也是 25。

image.png

你可能会问,前面的文章不是说,语句更新会生成 undo log(回滚日志)吗?那么,undo log 在哪呢?

实际上,上图中的三个虚线箭头,就是 undo log;而 V1、V2、V3 并不是物理上真实存在的,而是每次需要的时候根据当前版本和undo log 计算出来的。比如,需要 V2 的时候,就是通过 V4 依次执行 U3、U2 算出来。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/128114.html

相关文章

  • MySQL实战 | 02-MySQL 如何恢复到半个月内任意一秒的状态?

    摘要:如果这个时候发生非正常的服务重启,那么这些数据还没在内存,并没有同步到磁盘文件中注意,同步到磁盘文件是个随机,也就是会发生数据丢失。 原文链接:MySQL是如何做到可以恢复到任意一秒状态的? 看到这个题目是不是觉得数据库再也不用担心服务器 crash 了? 那我们需要学习为什么可以这么做?以及如何做? 即为什么可以恢复到任意时间点?如何恢复到任意时间点? 为什么有了 binlog 还需...

    Ocean 评论0 收藏0
  • 一条SQL语句在MySQL中如何执行的

    摘要:更新语句以上就是一条查询的执行流程,那么接下来我们看看一条更新语句如何执行的呢语句如下张三我们来给张三修改下年龄,在实际数据库肯定不会设置年龄这个字段的,不然要被技术负责人打的。 该文已加入笔主的开源项目——JavaGuide(一份涵盖大部分Java程序员所需要掌握的核心知识的文档类项目),地址:https://github.com/Snailclimb/JavaGuide 。觉得不错...

    roundstones 评论0 收藏0
  • 一条SQL语句在MySQL中如何执行的

    摘要:更新语句以上就是一条查询的执行流程,那么接下来我们看看一条更新语句如何执行的呢语句如下张三我们来给张三修改下年龄,在实际数据库肯定不会设置年龄这个字段的,不然要被技术负责人打的。 该文已加入笔主的开源项目——JavaGuide(一份涵盖大部分Java程序员所需要掌握的核心知识的文档类项目),地址:https://github.com/Snailclimb/JavaGuide 。觉得不错...

    Jason_Geng 评论0 收藏0
  • 浅析MySQL事务中的redoundo

    摘要:是负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性和操作实际上是系统调用函数,在很多持久化场景都有使用到,比如的持久化中也使用到两个函数。 我们都知道事务有4种特性:原子性、一致性、隔离性和持久性,在事务中的操作,要么全部执行,要么全部不做,这就是事务的目的。事务的隔离性由锁机制实现,原子性、一致性和持久性由事务的redo 日志和undo 日志来保证。所以本篇文章将讨论关于事务中的...

    Flands 评论0 收藏0
  • MySQL探秘(八):InnoDB的事务

    摘要:事务执行后,并没有破坏数据库的完整性约束。事务执行操作时,会将本事务相关的所有都进行落盘,只有所有落盘成功,才算成功。  事务是数据库最为重要的机制之一,凡是使用过数据库的人,都了解数据库的事务机制,也对ACID四个基本特性如数家珍。但是聊起事务或者ACID的底层实现原理,往往言之不详,不明所以。所以,今天我们就一起来分析和探讨InnoDB的事务机制,希望能建立起对事务底层实现原理的具...

    1treeS 评论0 收藏0

发表评论

0条评论

社区管理员

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<