MySQL在执行update操作时涉及到MySQL的日志系统:redo log和binlog。
一条简单的update语句如下:
mysql> update table1 set a = a+1 where id =1;
update语句的执行流程也会像查询语句的那一套流程:链接器→查询缓存→分析器→优化器→执行器→存储引擎。
不过update语句涉及到MySQL的日志模块:redo log(重做日志)和binlog(归档日志)
2.1 redo log
当一条更新语句过来,InnoDB引擎会先把记录写到redo log中,并更新内存,后续会在合适的时候写入磁盘,如果redo log写满了,InnoDB引擎会将一部分redo log记录写入磁盘。
redo log 在哪呢?它也是在磁盘上,这是一个写磁盘的过程,但是与更新过程不一样的是,更新过程是在磁盘上随机IO,费时。 而写redo log 是在磁盘上顺序IO。效率要高。
InnoDB的redo log是固定大小的,例如可以配置4个文件,每个文件的大小为1GB,那就共可以写入5GB的记录。redo log是一个环形数据结构,循环写,如下图所示:
redo log会有着write pos和check point来记录着当前写入位置和擦除位置,在记录擦除的时候,也就是把记录更新到磁盘上。
redo log 是 InnoDB引擎所特有的,我们如果再使用InnoDB引擎创建表时,如果数据库发生异常重启,之前提交的记录都不会丢失。 InnoDB正因为有了 redo log(重做日志),才有了 crash-safe 的能力(即使mysql服务宕机,也不会丢失数据的能力)。
redo log记录描述的是“在某个数据页上做了什么修改”,例如:MLOG_REC_UPDATE_IN_PLACE类型的REDO中记录了对Page中一个Record的修改,方法如下: (Page ID,Record Offset,(Filed 1, Value 1) … (Filed i, Value i) … ) 其中,PageID指定要操作的Page页,Record Offset记录了Record在Page内的偏移位置,后面的Field数组,记录了需要修改的Field以及修改后的Value。
2.2 binlog
redo log 是 InnoDB 引擎特有的日志,而 Server 层也有自己的日志,称为 binlog(归档日志)。
为什么会存在第二个日志?
- redo log是属于InnoDB引擎特有的,binlog是MySQL的Server层实现的,它可以被所有的引擎都可以使用。
- redo log 是物理日志,用来记录“在某个数据页上做了什么修改”,binlog是逻辑日志,用来记录语句的原始逻辑。
- redo log是循环写的,空间为固定大小;binlog是追加写的,当一个binglog文件写满之后,会切换到下一个文件,下一个binlog文件并不会覆盖前面的日志文件。
Binlog有两种模式,statement 格式的话是记sql语句, row格式会记录行的内容,记两条,更新前和更新后都有。
现在来看下update语句在执行器和InnoDB引擎的执行流程:
- 执行器先找引擎去ID=1的这一行数据,如果数据所在数据页在内存中,则直接返回给执行器;否则从磁盘将数据读入内存,然后返回给执行器。
- 执行器拿到数据后,将目标数值加一,得到新的一行数据,再调用引擎接口写入这行新数据。
- 引擎将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时的redo log处理prepare状态,然后告知执行器执行完成了,随时可以提交事务。
- 执行器生成这个操作的binlog,并把binlog写入磁盘。
- 执行器调用引擎的提交事务接口,引擎把刚刚的redo log改成提交(commit)状态,更新完成。
update流程图:
为什么会有两阶段提交?
redo log 负责事务; binlog负责归档恢复; 各司其职,相互配合,才提供(保证)了现有功能的完整性;
那我们用士兵埋雷,长官引爆的例子来解释:
binlog:它是用来记录逻辑意思,也就是它记录了“士兵去埋雷”这件事。
redolog:prepare状态时就是记录“士兵去埋雷”这个动作,commit状态就是“长官引爆”的这个动作
只有在完成redo log的prepare状态和binlog之后,才可以最终的commit。
问题练习:
为该讲的内容总结了几个问题, 大家复习的时候可以先尝试回答这些问题检查自己的掌握程度:
- redo log的概念是什么? 为什么会存在.
- 什么是WAL(write-ahead log)机制, 好处是什么.
- redo log 为什么可以保证crash safe机制.
- binlog的概念是什么, 起到什么作用, 可以做crash safe吗?
- binlog和redolog的不同点有哪些?
- 物理一致性和逻辑一直性各应该怎么理解?
- 执行器和innoDB在执行updae语句时候的流程是什么样的?
- 如果数据库误操作, 如何执行数据恢复?
- 什么是两阶段提交, 为什么需要两阶段提交, 两阶段提交怎么保证数据库中两份日志间的逻辑一致性(什么叫逻辑一致性)?
- 如果不是两阶段提交, 先写redo log和先写bin log两种情况各会遇到什么问题?