MySQL中常见的日志问题有哪些

介绍

小编给大家分享一下MySQL中常见的日志问题有哪些,希望大家阅读完这篇文章后大所收获、下面让我们一起去探讨吧!

MySQL里有两个日志,即:重做日志(重做日志)和归档日志(binlog)。

其中,binlog可以给备库使用,也可以保存起来用于恢复数据库历史数据。它是实现在服务器层的,所有引擎可以共用.redo日志是InnoDB特有的日志,用来支持crash-safe能力。

你一定听过MySQL事务的两阶段提交,指的就是在事务提交的时候,分成准备和提交两个阶段。

如图1所示为一个事务的执行流程,你在最后三步可以看的到,重做日志先准备完成,再写binlog,最后才进入重做日志提交阶段。

 MySQL中常见的日志问题有哪些

图1两阶段提交示意图

这里,我要先和你解释一个误会式的问题:这个图不就是一个更新语句的执行流程吗,怎么还会调用提交语句?

通常情况下,你会产生这个疑问的原因,在于把<强>两个 <强>“提交”的概念混淆了:

问题中的“提交语句”,是指MySQL语法中,用于提交一个事务的命令。一般跟开始/启动事务配对使用。

而我们图中用到的这个“提交步骤”,指的是事务提交过程中的一个小步骤,也是最后一步。当这个步骤执行完成后,这个事务就提交完成了。

“提交语句“执行的时候,会包含“提交步骤”。

而我们这个例子里面,没有显式地开启事务,因此这个更新语句自己就是一个事务,在执行完成后提交事务时,就会用到这个“提交步骤”。

接下来,我们就一起分析一下在<强>两阶段提交的不同时刻,MySQL异常重启会出现什么现象。

如果在图中时刻一个的地方,也就是写入重做日志处于准备阶段之后,写binlog之前,发生了崩溃(崩溃),由于此时binlog还没写,重做日志也还没提交,所以崩溃恢复的时候,这个事务会回滚。这时候,binlog还没写,所以也不会传到备库。到这里,我们都可以理解。

而我们理解会出现问题的地方,主要集中在时刻B,也就是binlog写完,重做日志还没提交前发生崩溃,那崩溃恢复的时候MySQL会怎么处理?

我们先来看一下崩溃恢复时的判断规则。

1,如果重做日志里面的事务是完整的,也就是已经有了提交标识,则直接提交;

2,如果重做日志里面的事务只有完整的准备,则判断对应的事务binlog是否存在并完整:

。如果是,则提交事务;

B。否,则回滚事务。

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

现在,我们就针对两阶段提交再继续延展一下。

问题1:MySQL怎么知道binlog是完整的?

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

如果碰到既有准备,又有提交的重做日志,就直接提交;

如果碰到只有parepare,而没有提交的重做日志,就拿着XID去binlog找对应的事务。

问题3:处于准备阶段的重做日志加上完整binlog,重启就能恢复,MySQL为什么要这么设计?

回答:其实,这个问题还是跟我们在反证法中说到的数据与备份的一致性有关。在时刻B,也就是binlog写完以后MySQL发生崩溃,这时候binlog已经写入了,之后就会被从库(或者用这个binlog恢复出来的库)使用。

所以,在主库上也要提交这个事务。采用这个策略,主库和备库的数据就保证了一致性。

问题4:如果这样的话,为什么还要两阶段提交呢?干脆先重做日志写完,再写binlog。崩溃恢复的时候,必须得两个日志都完整才可以。是不是一样的逻辑?

回答:其实,两阶段提交是经典的分布式系统问题,并不是MySQL独有的。

如果必须要举一个场景,来说明这么做的必要性的话,那就是事务的持久性问题。

对于InnoDB引擎来说,如果重做日志提交完成了,事务就不能回滚(如果这还允许回滚,就可能覆盖掉别的事务的更新)。而如果重做日志直接提交,然后binlog写入的时候失败,InnoDB又回滚不了,数据和binlog日志又不一致了。

两阶段提交就是为了给所有人一个机会,当每个人都说“我还好”的时候,再一起提交。

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

回答:我把这个问题再翻译一下的话,是说只保留binlog,然后可以把提交流程改成这样:……→“数据更新到内存”→“写binlog”→“提交事务”,是不是也可以提供崩溃恢复的能力?

MySQL中常见的日志问题有哪些