数据库

首页 » 常识 » 问答 » MySQL探秘恢复到任意时刻的秘诀
TUhjnbcbe - 2021/5/1 20:29:00
急性白癜风 https://m-mip.39.net/nk/mipso_4632312.html
一条更新语句的执行

MySQL恢复的秘密,藏在每一条SQL语句的执行里。于是,我们从一条简单的SQL语句说起。假设我们有一个表T,主键是intID,有一个字段intc。现在我们要将ID=2这一样的c值加1:

mysqlupdateTsetc=c+1whereID=2;

一条update语句执行的基本链路如下:

当我们执行语句之前,需要先连接数据库,这是连接器的工作。如果是select语句,会查询下缓存中是否存在结果。当然我们是update语句,不仅不会查询缓存,还会清空缓存。分析器通过词法和语法分析,判断出这是一条update语句,并找出需要更新的表和列。优化器会判断是否使用索引,并生成最终的执行计划执行计划由执行器负责执行

其他语句的执行步骤基本一致。但是,更新流程(如update和delete)还涉及了两个重要的日志模块:redolog(重做日志)和binlog(归档日志)。

临时账本:redolog

redolog是InnoDB引擎特有的日志系统。数据库的底层仍然是依赖文件系统进行持久化存储的。如果每一次更新操作都需要写磁盘,都需要在磁盘上寻找到那条记录的位置,再更新,整个过程的I/O成本、查找成本都是非常高的。

MySQL采用了WAL技术来解决这个问题。WAL,即Write-AheadLogging,它的主要思路就是,先写日志,再写磁盘。具体执行时,当有一条记录需要更新,InnoDB引擎会先把记录写到redolog里,并更新内存,这个时候整个更新过程就算结束了。InnoDB引擎会在适当的时候,将这个操作记录更新到磁盘里面,这个更新一般是在空闲的时候做。

InnoDB的redolog是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB。引擎将从文件头部开始写,写到末尾又会循环到开头继续写。如下图所示:

writepos是当前记录的位置,一边写一遍后移,相当于类似循环链表,写到第3号文件末尾后就回到文件开头。checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

上图中的,writepos后和checkpoint之前是redolog的空闲部分,可以用来记录新的操作。如果writepos追上checkpoint,表示redolog记满了。这时不能再进行新的更新,得停下来将一部分记录擦除(更新到磁盘),将checkpoint向前推进一些,才能继续响应更新。

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

归档日志:binlog

MySQL从整体来说可以分成两块,一块是Server层,它主要做的是MySQL功能层面的事情;还有一块是引擎层,负责存储相关的具体事宜。RedoLog是InnoDB引擎特有的日志,而Server层也有自己的日志,就是binlog(归档日志)。

那么为什么要有两份日志同时存在呢?

最初的MySQL中是没有InnoDB的。早期版本的MySQL默认引擎是MyISAM,MyISAM没有crash-safe能力,而binlog日志也只能用于归档使用。而InnoDB当时是另一个公司(InnobaseOy)以插件形式引入MySQL的,既然只依靠binlog是没有crash-safe能力的,所以InnoDB使用另外一套日志系统——也就是redolog来实现crash-safe能力。

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

redolog是InnoDB引擎特有的;binlog是MySQL的Server层实现的,只要是MySQL就可以使用redolog是物理日志(引擎层面),记录的是”在某个数据页上做了什么修改”;binlog是逻辑日志(Server层面),记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1”。redolog是循环写的,空间固定会用完;binlog是可以追加写入的。“追加写”是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

了解了这两个日志后,我们来看下执行器和InnoDB引擎在执行update语句的具体过程:

执行器先找引擎取ID=2这一行。ID是主键,引擎直接用树(B+树)搜索找到这一行。如果ID=2这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。执行器拿到引擎给的行数据,把这个值加上1,比如原来是N,现在就是N+1,得到新的一行数据,再调用引擎接口写入这行新数据。引擎将这行新数据更新到内存中,同时将这个更新操作记录到redolog里面,此时redolog处于prepare状态。然后告知执行器执行完成了,随时可以提交事务。执行器生成这个操作的binlog,并把binlog写入磁盘。执行器调用引擎的提交事务接口,引擎把刚刚写入的redolog改成提交(
1
查看完整版本: MySQL探秘恢复到任意时刻的秘诀