MySQL分层架构之bin log和redo log介绍

MySQL架构

  • 架构分层

    MySQL架构分层图

    MySQL整体分为3层:客户端层,Server层和存储引擎层

    1. binlog日志由Server层生成;

    2. redo log是InnoDB特有的日志,由InnoDB引擎生成

归档日志(binlog)

内容介绍

  • 概念

    数据库的Server层面,也有自己的日志,称为binlog(归档日志)

  • 理解逻辑日志binlog

  1. 写入新binlog文件,不让之前的逻辑影响

执行一次flush logs命令行,就会在data目录下新增一个mysql-bin.00000x文件


     ## 登陆MySQL命令行
     mysql -uroot -p

     ## 刷新binlog
     flush logs;

     ## 确认刷新binlog成功
     show master status;

     ## 查询binlog日志位置
     show variables like 'log_bin%';

  1. 测试数据

     ## 创建表
     CREATE TABLE `User`  (
     `id` int(11) NOT NULL AUTO_INCREMENT,
     `name` varchar(10) CHARACTER SET gb2312 COLLATE gb2312_chinese_ci NOT NULL,
     `age` int(11) UNSIGNED NOT NULL,
     PRIMARY KEY (`id`) USING BTREE
     ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Compact;

     ## 新增
     INSERT `User` VALUES("1", "张三", 18);
     INSERT `User` VALUES("2", "李四", 20);

     ## 修改
     DELETE FROM `User` WHERE id = 1;


  1. 翻译binlog二进制文件

     sudo /usr/local/mysql/bin/mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000006 > mysqlbin.sql


binlog二进制文件翻译结果

这是翻译出来的sql文件,是因为我在mysqlbinlog -v参数加工而成的。

  • 总结

    逻辑日志里边就是记录着sql语句,通过sql语句记录着逻辑的变化,比如insert, update等动作,但不是记录具体数据,那个由物理日志完成

特点分析

  • 与redo log的区别

    1. redo log是innoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都能使用;

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

  • binlog写入策略

    通过与redo log的区别,我们知道,binlog是追加写入的,所以与redo log写入相比,没有擦除的概念

    写入逻辑

    事务执行过程中,先把日志写到binlog cahce,事务提交的时候,再把binlog cache写到binlog文件中(落盘)

    binlog文件写入流程

    流程分析

    1. 每个线程都有自己的binlog cache,但是共用同一份binlog文件;

    2. 图中的write,指的就是把日志写入到数据库系统的page cache,并没有把数据持久化到磁盘,所以速度很快;

    3. 图中的fsync,才是将数据持久化到磁盘的操作;

    4. 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 个事务的 binlog 日志

重做日志(redo log)

  • 概念介绍

    InnoDB为了能够支持事务一系列操作,而事务有4种特性(ACID):原子性、一致性、隔离性、持久性,在事务操作中,要么全部执行,要么全部不执行,这就是事务的目的。

    而我们的redo log用来保证事务的持久性,即我们常说的ACID中的D。这里的说的持久性,是说最后落盘到redo log文件(即常见的ib_logfile文件),因为最后我们异常情况的恢复,都是根据文件来做恢复的。

  • WAL(预写日志Write Ahead Log)

    在计算机体系中,CPU处理速度和硬盘的速度,是不在同一个数量级上的,为了让它们速度匹配,从而催生了我们的内存模块,但是内存有一个特点,就是掉电之后,数据就会丢失,不是持久的,我们需要持久化的数据,最后都需要存储到硬盘上。

    InnoDB引擎设计者也利用了类似的设计思想,先写内存,在写硬盘,这样就不会因为redo log写硬盘IO而导致数据库性能问题。在InnoDB中,这种技术有一个专业名称,叫做Write-Ahead-Log(预先日志持久化)

    redo log buffer --(write)–> page cache --(fsync)–> 磁盘文件

  • redo log写入策略

    上边是保证了处理的速度,但是怎么样保证写入到硬盘的可靠性呢?

    InnoDB引擎的设计者也设计了一种写入的策略,首先有一个后台线程,每隔1秒,就会把redo log buffer中的日志,调用write写到文件系统的page cache,然后调用fsync持久化到磁盘(即redo log文件 ib_logfile0 ib_logfile1)。

    为了控制redo log写入策略,InnoDB提供了innodb_flush_log_at_trx_commit配置参数,它有三种取值:

    1. 设置为 0 的时候,表示每次事务提交时都只是把 redo log 留在 redo log buffer 中;

    2. 设置为 1 的时候,表示每次事务提交时都将 redo log 直接持久化到磁盘

    3. 设置为 2 的时候,表示每次事务提交时都只是把 redo log 写到 page cache

    如果不是对性能要求高的,一般把该参数设置为 1。

  • redo log的擦除

    通过上边的设计,速度和可靠性的问题都解决了,但是我们仔细想想,还会有什么问题?

    随着文件的增加,落盘的速度会越来越慢,这里就涉及到一个删除日志文件的算法,即我们的redo log擦除

    redo log 的大小是固定的,比如可以配置一组4个文件,每个文件大小是8M,那么这个redo log总共就可以记录32M的操作,这个参数可以通过innodb_log_file_size设置

    下图是具体的擦除算法:ib_logfile 从头开始写,写到末尾就又回到开头循环写

    redo log擦除示意图

    write pos是当前记录的位置,一边写一边后移,写到第3号文件末尾后就回到0号文件开头。checkpoint是当前要擦除的位置,也是往后移动并且循环的,擦除记录前要把记录更新到数据文件,write pos与check point之间为剩余可用写入的空间

    何时会擦除redo log并更新到数据文件中

    1. 系统空闲时;

    2. Redo log文件没有空闲空间时,即write pos追上check point的时候;

    3. MySQL Server正常关闭时

  • crash-safe

    redo log的存在使得数据库具有crash-safe能力,即如果Mysql 进程异常重启了,系统会自动去检查redo log,将未写入到Mysql的数据从redo log恢复到Mysql中去。

    当数据库发生异常重启时,系统会自动定位到上次checkpoint的位置,同时,每个数据页中也存在一个LSN,当redo log中的LSN大于数据页中的LSN时,说明重启前redo log中的数据未完全写入数据页中,那么将从数据页中记录的LSN开始,从redo log中恢复数据。

    比如redolog 的LSN 是 13000,数据库页的LSN是 10000,那么说明重启前有部分数据未完全刷入到磁盘的数据页中,那么系统将会恢复redo log 中LSN从10000开始到13000的记录到数据页中。

    当redo log中的LSN小于数据页中的LSN时,说明数据页已经被刷到该位置,所以不需要进行恢复。

两阶段提交(2PC)

  • 内容介绍

    这里讲的两阶段提交,就是纯粹的指redo log和binlog日志的两阶段提交

    而两阶段提交的目的就是让redo log和binlog两个日志逻辑上一致

    如果redo log持久化并进行了提交,而binlog未持久化数据库就crash了,则从库从binlog拉取数据会少于主库,造成不一致。因此需要内部事务来保证两种日志的一致性

    MySQL两阶段提交

  • 流程分析

    1. 将语句执行;

    2. 记录redo log,并将记录状态设置为prepare;

    3. 通知Server,已经修改好了,可以提交事务了;

    4. 将更新的内容写入binlog;

    5. commit,提交事务;

    6. 将redo log里这个事务相关的记录状态设置为commited

    prepare: redolog写入log buffer,并fsync持久化到磁盘,在redolog事务中记录2PC的XID,在redolog事务打上prepare标识。

    commit: binlog写入log buffer,并fsync持久化到磁盘,在binlog事务中记录2PC的XID,同时在redolog事务打上commit标识 其中,prepare和commit阶段所提到的“事务”,都是指内部XA事务,即2PC

  • 恢复步骤

    redolog中的事务如果经历了2PC中的prepare阶段,则会打上prepare标识,如果经历commit阶段,则会打上commit标识(此时redolog和binlog均已落盘)。

    1. 按顺序扫描redolog,如果redolog中的事务既有prepare标识,又有commit标识,就直接提交(复制redolog disk中的数据页到磁盘数据页)。

    2. 如果redolog事务只有prepare标识,没有commit标识,则说明当前事务在commit阶段crash了,binlog中当前事务是否完整未可知,此时拿着redolog中当前事务的XID(redolog和binlog中事务落盘的标识),去查看binlog中是否存在此XID

      a. 如果binlog中有当前事务的XID,则提交事务(复制redolog disk中的数据页到磁盘数据页)。

      b. 如果binlog中没有当前事务的XID,则回滚事务(使用undolog来删除redolog中的对应事务)。

    可以将mysql redolog和binlog二阶段提交和广义上的二阶段提交进行对比,广义上的二阶段提交,若某个参与者超时未收到协调者的ack通知,则会进行回滚,回滚逻辑需要开发者在各个参与者中进行记录。mysql二阶段提交是通过xid进行恢复

参考链接

  • MySQL的redo log和bin log 真香

    https://mp.weixin.qq.com/s/M5CXNhMEh2QCLZp59HsSbA

  • Mysql面试题系列-什么是crash-safe能力?什么是两阶段提交?

    https://blog.csdn.net/Belingda/article/details/107172933

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: MySQL中的undologredolog是两种不同的日志文件。 undolog是用于事务回滚的日志文件,它记录了事务执行前的数据状态,当事务回滚时,可以根据这些记录将数据恢复到事务执行前的状态。 redolog是用于崩溃恢复和数据恢复的日志文件,它记录了MySQL数据库中所有的修改操作,当MySQL崩溃或者出现其他异常情况时,可以根据redolog中的记录将数据恢复到最近一次提交的状态。 ### 回答2: MySQL中的undologredolog是两个重要的日志文件,用于维护数据的一致性和恢复。 undolog(回滚日志)是用于回滚操作的日志,它记录了事务对数据库的修改操作,在回滚时可以利用undolog将数据恢复到事务开始前的状态。undolog文件是在InnoDB存储引擎中使用的,它采用了"write ahead logging"(先写日志,再写磁盘)的机制,保证事务的原子性和一致性。 redolog(重做日志)是用于恢复操作的日志,它记录了事务对数据库的修改操作,在数据库崩溃或意外断电等情况下,通过读取redolog可以将数据库恢复到最后一次提交事务的状态。redolog文件是在InnoDB存储引擎中使用的,默认情况下是循环写入,即满了后会从头开始覆盖,以保证磁盘空间的有效利用。 undologredolog的作用不同,undolog主要用于事务回滚,redolog用于恢复数据库。在事务进行过程中,先将数据的修改操作写入undolog,然后再写入redolog,只有当redolog写入成功后,事务才会提交完成。这样可以保证在数据库崩溃后,借助redolog进行恢复操作,将未写入磁盘的undolog日志进行恢复。 总结来说,undolog是用于回滚操作,保证了事务的原子性和一致性;redolog是用于恢复操作,保证了数据库的持久性。两者共同作用,保证了MySQL数据库的安全可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值