1、MySQL逻辑框架图
更新语句涉及两个重要的日志模块:redo log (重做日志)和binlog(归档日志)
2、redo log
当有一条更新语句的时候,InnoDB引擎就会将记录写到redo log里, 并更新内存,这个时候更新就算完成了。同事,InnoDB在适当的时候,将这个操作的记录更新到磁盘里面,这个更新往往是系统空闲的时候。
我们可以将,InnoDB的redo log 配置为一组4个文件,每个文件1G,一共4G.从头开始写,写到末尾就又回到开头循环写,如下图:
write pos 记录当前的位置,一边写一边往后移动,写到3号文件末尾就回到0号文件开头。 checkpoint 是当前要擦除的位置, 也是往后移动且循环的,擦除记录前需要先更新到文件。write pos 与 checkpoint之间空闲的部分,可以用来记录新操作。如果write pos 追上 checkpoint 这时候就需要先停下来擦除一些记录以后再把 checkpoint 推进一下。
3、binlog
MySQL整体来看,其实就两块:
一块是Server层,它主要做MySQL功能层面的事情,其日志是binlog;
另一块是引擎层,负责存储相关的事宜,其日志是redo log;
正两种日志的不同点:
redo log 是 InnoDB引擎持有的;binlog 是Server层实现的,所有引擎都可用;
redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的语句原始逻辑,比如:“给ID=2这一行的c字段加1”;
redo log 是循环写, 空间固定会写完;binlog 是可以追加写,写完一个一定大小文件后切换到下一个文件写,不会覆盖以前的文件;
4、update 语句执行流程
例如分析这个sql 语句
mysql> update T set c=c+1 where ID=2;
1)执行器先找引擎去ID=2 这一行;如果ID=2 这一行所在数据页本来就在内存,就直接返回执行器;否则需要先从磁盘读入内存,然后在返回;
2)执行器拿到数据后,在c值上加1 得到新的行数据,再调用引擎接口写入这行数据。
3)引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器,随时可以提交事务。
4)执行器生成这个操作的binlog ,并把binlog 写入磁盘。
5)执行器调用引擎的提交事务接口, 引擎将刚写入的redo log 改为commit 状态, 更新完成。
5、两阶段提交
第一阶段:redo log 已经更新到引擎内存中,并通知 执行器随时可以提交事务;
第二阶段: 执行器写 binglog 文件 , 并调用引擎提交事务接口,引擎将redo log 改为 commit 状态;
两阶段提交可以保证数据库异常重启后,之前提交的数据不会丢失,这个能力叫 crash-safe;