mysql prepare 日志,mysql---日志

简介

mysql更新流程涉及两个重要的日志模块,redo log(重做日志)和 binlog(归档日志)。还有个

1、redo log(重做日志)

mysql的redo log(重做日志)就相当于我们日常上课时因为时间紧急,只能在草稿本上记录一下日记的重点,等到课下时间充裕的时候,根据草稿本上的重要日志仔细的归纳到我们的日记本上。

其实不只是我们上课时间不足,在 MySQL 里也有这个问题,如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后再更新,整个过程 IO 成本、查找成本都很高。为了设计出低成本的更新,mysql的设计者设计出了模仿我们在草稿本上记录日记的思路,开发出了redo log(重做日志)。

而这个过程,其实就是 MySQL 里经常说到的 WAL 技术,WAL 的全称是Write-Ahead Logging,它的关键点就是先写日志,再写磁盘,也就是先写到草稿本上,等不忙的时候再汇总到日记本。

具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log(草稿本)里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做的,相当于我们的整理到日记本上的过程。

InnoDB 的 redo log 是固定大小的,可以由我们配置,并且当我们整理到磁盘后以后,可以擦除redo log的空间。整个过程是从头开始写,写到末尾就又回到开头循环写。如果一次的redo log记录超过了这个空间大小,而前面的我们还没有整理到磁盘,这个时候就需要停下来,先整理一部分后,继续写。

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

2、binlog(归档日志)

binlog日志我们可能相当的熟悉,可能使用过mysql的人都用这个查过业务。MySQL 整体来看,其实就有两块:一块是 Server 层,它主要做的是 MySQL功能层面的事情;还有一块是引擎层,负责存储相关的具体事宜。上面的redo log 是 InnoDB 引擎特有的日志,而 Server 层也有自己的日志,称为 binlog(归档日志)。

那我们又要问了,既然有了redo log日志,binlog日志还有存在的必要吗/

答案是必然的!因为binlog日志要早于redo log日志,并且redo log日志是引擎层面实现的,并且是innoDB引擎,如果取消了binlog,我们不使用innoDB引擎,那不是没有日志可记了,并且最开始mysql是没有innoDB引擎的。

这两种日志有以下三点不同。

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

以使用。

redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,

记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。

redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指

binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

而且binlog日志的作用是不可替代的,想象一下,备份库的时候只依赖redo log能行吗?而且两个日志设计的时候是为了解决不同问题的,不在一个维度上,所以不能比较好坏、不能一个替代一个,更不能说那个没用。

下面我们用一个实例来解释个个日志在什么时候起作用;

例:update student set name = xiaoming where id =1

我们再来看执行器和 InnoDB 引擎在执行这个简单的 update语句时的内部流程。

1. 执行器先找引擎取 id=1 这一行。id 是主键,引擎直接用树搜索找到这一行。如果 id=1这一行所在的数据页本来就在内存中,就直接返回给执行器;

否则,需要先从磁盘读入内存页,找到数据,然后再返回。

2. 执行器拿到引擎给的行数据,把这个行的name赋值为xiaomning,得到新的一行数据,再调用引擎接口写入这行新数据。

3. 引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redolog 处于 prepare 状态。然后告知执行器执行完成了,

随时可以提交事务。

4. 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。

5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。

将 redo log 的写入拆成了两个步骤:prepare和 commit,这就是"两阶段提交"。

我们再猜想下,在上面的过程3、4分别遇到了异常,退出了,会发生什么?并且mysql恢复后怎么实现数据一致性。

在3之后发生后异常,因为还没有写binlog日志,而且redolog 处于 prepare 状态。遇到异常,事务肯定回滚,你用binlog恢复库不会出现问题,并且也没有这个条更新的redolog。

在4之后发生异常,binlog已经写下了,这个时候突然断电,mysql服务发生异常停了,这个时候重启以后。如果redo log发生异常回滚了,这个时候binlog已经记录了,但是没有记录redo log,往磁盘更新的时候也不会更新进去,这不就出问题了吗?确实是这样的。如果binlog 已经记录,并且redo log在 prepare 状态,在mysql恢复过来后如果认可这条记录,是不是也就没啥问题了。

Binlog有两种模式,statement 格式的话是记sql语句, row格式会记录行的内容,记两条,更新前记录和更新后记录都有。

其实,在mysql中还有一种日志,是为了支持事务发生异常回滚的,叫undo log(回滚日志)。具体后面再展开学习吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值