mysql中一条SQLupdate语句是如何执行的?redo log 与binlog

mysql> create table T(id int primary key,c int);

mysql> update T set c=c+1 where id=2;

大体流程与查询流程是一样的:先是检查连接权限,然后经过分析器,知道是更行语句,查询缓冲遇到更行语句就清空该表的查询缓存;优化器决定使用id这个索引并生成执行计划;执行器负责执行,找到这一行,并进行更行。

与查询流程不一样的是:更新流程还涉及两个重要的日志模块:redo log与binlog(归档日志)

………………………………………………………………………………………………………………………………………………

Redo log

一个店家有两个账本,A一个记录了所有的客户消费信息与欠账信息;

可日常繁忙时,无法快速定位将客人信息记录到A中,这时就需要临时有一个B,随时记录客人消费信息;等晚上客人走了,再将B中的信息整理到A中;

B账本就是redo log

……………………………………………………………………………………………………………………………………………………

Mysql里也有这个问题,如果每一次的更行操作都需要写入磁盘,然后磁盘也要找到对应的那条记录,然后再更行,整个过程IO成本,查找成本会很高。

Mysql就找到一种解决方法:就是WAL技术:先写日志,再写磁盘。

具体来说:当有一条记录需要更新的时候,INNODB引擎就会把记录写到redo log,并更行内存,这个时候更新就算完成了;同时,innodb引擎会在适当的时候,将这个操作记录更新到磁盘里面。

……………………………………………………………………………………………………………………………………

店铺掌柜,发现B账本快写满了,那么他就会将已经写进A账本的记录擦掉,就有了剩余空间,继续往里面写记录

……………………………………………………………………………………………………………………………………

mysql中一条SQLupdate语句是如何执行的?redo log 与binlog_第1张图片

write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

如果wiite pos 追上了checkpoint,表示redo已经满了,不能继续执行更行操作了,要停下来,等checkpoint向前推移,有了剩余空间,再继续更新

…………………………………………………………………………………………………………………………………………

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

Redolog 不是记录数据页“更改之后的状态”,而是记住“页做了什么改动”

Binlog有两种模式,statement格式记录sql语句;row格式记录行内容:更行前后都有

一般选用row模式,因为遇到主从不一致时,row模式,更改前后都有,恢复之后,不会丢失某个事务的数据。

两种日志的不同:

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

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

2 redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。

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

……………………………………………………………………………………………………………………………………………………

Binlog或redolog可以二选一吗?

首先,redo log只有innodb引擎才有,所以不能丢;redo log不具备归档的功能,刷到磁盘后就被清除了;而binlog是追加,可以归档,用作数据库恢复,数据库扩容都很重要。

……………………………………………………………………………………………………………………………………………………

mysql中一条SQLupdate语句是如何执行的?redo log 与binlog_第2张图片

执行器先找引擎取ID=2,ID是主键,引擎通过索引快速找到ID=2这一行;如果这一行本就在内存中,就直接返回给执行器;否则需要从磁盘读入内存,然后再返回。

执行器拿到引擎给的行数据,把这个值加1,得到新的行数据,再调用引擎接口写入这行新数据。

引擎将这行数据更新到内存中,同时将这个更行操作记录到redo log中,此时redo log处于prepare状态。然后告知执行器执行完成了,随时可以提交事务。

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

执行器调用引擎接口,引擎把redo log 改成commit状态,更新完成。

最后三步看上去有点绕,将redo log写入拆分为两个步骤:prepart和commit------两阶段提交。

…………………………………………………………………………………………………………………………………………

内容主体来自林晓斌老师《mysql实战45讲》

你可能感兴趣的:(SQL,数据库)