美文网首页
【MySQL】15|日志和索引相关问题

【MySQL】15|日志和索引相关问题

作者: 学而思之 | 来源:发表于2022-01-21 22:36 被阅读0次

1 在两阶段提交的不同瞬间,MySQL如果发生异常重启,是怎么保证数据完整性的?

我们先来看下,两阶段提交的图

两阶段提交

如果在图中时刻1⃣️的地方,也就是写入redo log处于prepare阶段之后、写入binlog 之前,发生了崩溃。

由于此时binlog 还没写,redo log也还没提交,所以崩溃恢复的时候,这个事务会回滚。此时,binlog还没写,所以也不会传到备库。

如果在图中时刻2⃣️的地方,也就是binlog 写完,redo log还没commit前发崩溃,那崩溃恢复的时候MySQL会怎么处理?

我们先来看下崩溃恢复的判断规则:

  1. 如果redo log 里面的事务是完整的,也就是已经有了commit 标识,则直接提交
  2. 如果redo log 里面的事务只有完整的 prepare,则判断对应的事务 binlog 是否存在并完整:
    1. 如果是,则提交事务
    2. 如果否,则回滚事务

这里,时刻2⃣️发生崩溃对应的就是2(a) 的情况,崩溃恢复过程中事务会被提交。

2 MySQL 是怎么知道 binlog 是完整的?

一个事务的 binlog 是有完整格式的:

  • statement 格式的 binlog,最后会有commit
  • row 格式的 binlog,最后会有一个 XID event

另外,在MySQL 5.6.2 版本之后,还引入了 binlog-checksum 参数,用来验证 binlog 内容的正确性。对于binlog 日志由于磁盘原因,可能会在日志中间出错的情况,MySQL可以通过checksum的结果来发现。所以,MySQL还是有办法验证事务binlog 完整性的。

3 redo log 和 binlog 是怎么关联起来的?

它们有一个共同的数据字段,加XID。崩溃恢复的时候,会按顺序扫描 redo log:

  • 如果碰到既有 prepare、又有 commit 的 redo log,就直接提交
  • 如果碰到只有 prepare、而没有 commit 的 redo log,就拿着 XID 去 binlog 找对应的事务

4 处于 prepare 阶段的 redo log 加上完整的 binlog,重启就能恢复,MySQL 为什么要这么设计?

在binlog 写完之后MySQL 发生崩溃,这时候binlog 已经写入了,之后就会被从库(或者用这个 binlog 恢复出来的库)使用,所以为了保证一致性,这样设计的。

5 如果这样的话,为什么还要两阶段提交?直接redo log 写完,再写binlog。崩溃恢复的时候,必须得两个日志都完整才可以。是不是也一样的逻辑?

从事务的持久性来说,如果不需要两阶段提交。那么redo log 写完就算提交完成,如果之后 binlog 写入的时候失败,此时 InnoDB 又不能回滚(如果能回滚则可能会覆盖掉其他事务的更新),数据和binlog 日志就不一样了。

两阶段提交就是为了保证双方都完成的时候,再一起提交。

6 不引入两个日志,也就没有两阶段提交的必要了。只用binlog 来支持崩溃恢复,又能支持归档,不就可以了?

目前 binlog 不支持崩溃恢复,而redo log 支持事务和崩溃恢复。

7 只用 redolog,不用binlog

如果只从崩溃恢复的角度来讲是可以的。可以把binlog 关掉,这样就没有两阶段提交了,但系统依然是crash-safe的。

但是binlog 有着不可替代的功能:

  1. 归档日志功能
  2. binlog 作为MySQL 一开始就有的功能,被用在了很多地方,无法替代

8 redo log 一般设置多大

redo log 太小的话,会导致很快就被写满,然后不得不强行刷 redo log,这样WAL机制的能力就发挥不出来了。

可以将redo log 设置为 4个文件,每个文件1GB大小。

9 正常运行中的实例,数据写入后的最终落盘,是从redo log 更新过来的还是从 buffer pool 更新过来的?

redo log 并没有记录数据页的完整数据,所以它并没有能力自己去更新磁盘数据页,也就不存在“数据最终落盘,是由 redo log更新过去”的情况。

  1. 如果是正常运行的实例的话,数据页被修改后,跟磁盘的数据页不一致,称为脏页。最终数据落盘,就是把内存中的数据页写盘。这个过程,甚至与 redo log 毫无关系。
  2. 在崩溃恢复的场景中,InnoDB 如果判断到一个数据页可能在崩溃恢复的时候丢失了更新,就会将它读到内存,然后让redo log 更新内存内容。更新完成后,内存页变成脏页,就回到了第一种状态的情况。

10 redo log buffer 是什么?是先修改内存,还是先写 redo log 文件?

在一个事务的更新过程中,日志是要写多次的。比如 多个 insert 、update 语句,这个事务要进行多次更新,每次更新生成的日志都得先保存起来,但又不能在还没 commit 的时候就写到 redo log 文件里。

redo log buffer 就是一块内存,用来先存 redo 日志的。也就是说,在执行第一个 insert 的时候,数据的内存被修改了,redo log buffer也写入了日志。

但是,真正把日志写到redo log 文件,是在执行commit 语句的时候做的。

相关文章

  • 【MySQL】15|日志和索引相关问题

    1 在两阶段提交的不同瞬间,MySQL如果发生异常重启,是怎么保证数据完整性的? 我们先来看下,两阶段提交的图 如...

  • 15 | 答疑(一):日志和索引相关问题

    日志相关问题 两阶段提交不同瞬间,MySQL异常重启,怎么保证数据完整? 不是update 语句执行流程吗,怎么调...

  • 15 | 答疑文章(一):日志和索引相关问题

    在两阶段提交的不同瞬间,MySQL 如果发生异常重启,是怎么保证数据完整性的? https://time.geek...

  • 15 - 日志的相关问题

    关键字 日志、索引 这一章是专栏老师的答疑课,在这一节中,主要解决了一些关于日志和索引的疑惑。 日志相关问题 在第...

  • MySQL索引和SQL调优

    MySQL索引和SQL调优 本文有参考网上其他相关文章,本文最后有附参考的链接 MySQL索引 MySQL支持诸多...

  • MySQL索引和SQL调优

    MySQL索引和SQL调优 本文有参考网上其他相关文章,本文最后有附参考的链接 MySQL索引 MySQL支持诸多...

  • MySQL索引和SQL调优

    [TOC] MySQL索引和SQL调优 本文有参考网上其他相关文章,本文最后有附参考的链接 MySQL索引 MyS...

  • 大厂面试系列(八):数据库mysql相关

    数据库相关 mysql索引的数据结构,加索引的原则 InnoDB和myiasm的区别,以及常见的mysql优化方案...

  • MySQL物理结构

    MySQL是通过文件系统对数据和索引进行存储的。 MySQL从物理结构上可以分为日志文件和数据索引文件。 MySQ...

  • MySQL优化----SQL语句和索引优化

    sql及索引优化 如何发现有问题的sql? 使用Mysql的慢查询日志对有效率问题的SQL进行监控 慢查询日志所包...

网友评论

      本文标题:【MySQL】15|日志和索引相关问题

      本文链接:https://www.haomeiwen.com/subject/itvyhrtx.html