被面试官问住了,MySQL两阶段提交是什么鬼?

数据库 MySQL
MySQL中既存在redo log,又存在bin log,这是因为Bin Log是MySQL Server提供的一种归档日志,其本身并不具备Crash-Safe能力。而Redo Log本身不具备归档能力,他是一种循环写的日志。

前言

MySQL通过两阶段提交的机制,保证了redo log和bin log的逻辑一致性,进而保证了数据的不丢失以及主从库的数据一致。

而说起两阶段提交,就不得不先介绍一下redo log和bin log。

redo log

redo log即重做日志,是InnoDB引擎特有的一种日志(有的面试官经常问到这一点)。

redo log主要做什么呢?

以更新数据为例,我们知道,MySQL的数据是存储在磁盘上的,如果每一次更新数据,都去磁盘寻址找到要更新的数据,进行更新操作的话,这个IO成本是非常高的。

如果是固态硬盘还好,如果是机械硬盘,那么MySQL的更新性能根本无法满足我们的业务需要。

所以,MySQL采用了一种叫做WAL的技术,Write-Ahead Logging。

当更新数据时,将更新操作(即某个数据页上做了什么修改)先写到redo log里面,然后更新内存,这个更新操作就算完成了。MySQL会在服务器空闲的时候,把redo log的操作记录刷新到磁盘里,以保持数据的一致性。

需要注意的是,redo log虽然也是磁盘上的一个文件,但是由于操作是顺序写,所以性能是非常高的。

当然了,redo log也是有大小上限的,不可能无限制的写入。

以上图为例,配置了4个redo log,write pos就是代表当前记录写到什么位置了,而check point表示一个推进点,它会不断的前移,做擦除数据的操作,以保证redo log可以不断的写入。

当然,擦除数据之前,会把redo log的记录刷新到磁盘。

通过redo log,可以保证即使MySQL发生异常重启,数据也不会丢失(因为redo log是物理日志,可以进行重放),这个特性就叫做crash-safe。

bin log

bin log是MySQL Server提供的一种日志,叫做归档日志,所有引擎都可以使用bin log。

那bin log和redo log的区别是什么呢?

1,这两种日志的提供者不同:bin log是由MySQL Server提供的,redo log是InnoDB引擎特有的。

2,redo log主要记录的是某个数据页做了什么修改,bin log记录的是语句的原始逻辑,比如更新了某一行的某个字段。

3,redo log是循环写的,数据会被覆盖。bin log是追加写,一个文件写满,就写下一个文件。

两阶段提交

介绍完了redo log和bin log,我们再看一下他们两者是如何配合完成两阶段提交的。

上图就是一个更新数据的流程,可以看到,在更新一条数据之前,MySQL会先将数据加载到内存,然后更新内存,开始写redo log。

此时,redo log处于prepare状态,等到bin log写完之后,再提交事务,这一条记录的更新操作就算完成了。

redo log prepare -> 写bin log -> redo log commit,这个流程就叫做两阶段提交。

下面我们分析一下,采用两阶段提交的好处。

情景一,redo log处于prepare状态时,如果写bin log失败了,那么更新失败,此时redo log没有commit,bin log也没有记录,两者的状态是一致的,没有问题。

情景二,redo log处于prepare状态时,写bin log成功,但是宕机导致commit失败了。此时bin log产生了记录,redo log没有写入成功,数据暂时不一致。

但是不用担心,当MySQL重启时,会检查redo log中处于prepare状态的记录。在redo log中,记录了一个叫做XID的字段,这个字段在bin log中也有记录,MySQL会通过这个XID,如果在bin log中找到了,那么就commit这个redo log,如果没有找到,说明bin log其实没有写成功,就放弃提交。

通过这样的机制,保证了redo log和bin log的一致性。

总结

之所以MySQL中既存在redo log,又存在bin log,这是因为bin log是MySQL Server提供的一种归档日志,其本身并不具备crash-safe能力。而redo log本身不具备归档能力,他是一种循环写的日志。

MySQL通过将这两种日志整合起来,并通过两阶段提交的机制,保证了数据的一致性。

责任编辑:姜华 来源: 今日头条
相关推荐

2022-03-28 10:44:51

MySQL日志存储

2020-06-22 07:47:46

提交面试官订单

2020-08-03 07:04:54

测试面试官应用程序

2017-08-30 18:15:54

MySql

2020-05-12 11:05:54

MySQL索引数据库

2018-10-29 08:44:29

分布式两阶段提交事务

2022-12-21 19:04:35

InnoDBMySQL

2019-10-21 09:56:37

MySQLCOUNTInnoDB

2021-06-03 08:55:54

分布式事务ACID

2020-02-03 12:12:28

MySQL数据库SQL

2021-03-16 22:25:06

作用域链作用域JavaScript

2015-11-12 10:03:34

前端H5web

2021-03-17 08:39:24

作用域作用域链JavaScript

2021-09-07 10:44:33

Java 注解开发

2019-12-02 10:51:11

Redis存储系统

2021-05-19 08:40:36

DNS 协议查询

2022-12-27 08:39:54

MySQL主键索引

2021-12-17 07:30:42

排序算法效率

2020-12-29 06:51:32

线程源码SQL

2022-09-29 07:30:57

数据库索引字段
点赞
收藏

51CTO技术栈公众号