日志:
重做日志(redo log)和 归档日志(binlog)
redo log
1、Mysql 有一种技术叫 WAL : Write_Ahead Logging。即:先写日志,再写磁盘。是引擎层的日志
2、redo log 的大小是固定,类似一种闭环,其中两个关键点是:
write pos :当前记录位置
checkpoint:当前要擦除的位置
write pos 和 checkpoint 之间空的部分,就是用来写数据的,一旦当 write pos 追上 checkpoint 那么就不能在执行更新需要停下来,把 checkpoint 推进一点。
其中checkpoint 表示已经刷新到磁盘上的日志序列号,即LSN。
另外,每个页上也会记录一个LSN,用于表示已经刷新的数据。
3、InnoDB 正是因为有了 redo log 所以才是:crash-safe 的。
redo log的存在使得数据库具有crash-safe能力,即如果Mysql 进程异常重启了,系统会自动去检查redo log,将未写入到Mysql的数据从redo log恢复到Mysql中去。
当数据库发生异常重启时,系统会自动定位到上次checkpoint的位置,同时,每个数据页中也存在一个LSN,当redo log中的LSN大于数据页中的LSN时,
说明重启前redo log中的数据未完全写入数据页中,那么将从数据页中记录的LSN开始,从redo log中恢复数据。
比如redolog 的LSN 是 13000,数据库页的LSN是 10000,那么说明重启前有部分数据未完全刷入到磁盘的数据页中,那么系统将会恢复redo log 中LSN从10000开始到13000的记录到数据页中。
binlog
1、是server 层的日志
2、 redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用
redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
两阶段提交
1、为什么要两阶段提交,为了两份日志的数据一致。
例如:update T set count = count +1 WHERE id = 2
那么就是要
1、先去ID = 2 这行,如果数据在内存中,直接返回,如果不在内存中,那么就要读磁盘进入内存,返回行数据
2、执行引擎拿到这条数据,把值加1,再 调用引擎接口写入这行数据。
3、新行更新内存,同时写入 redo log,处于prepare 状态,阶段
4、执行器,写binlog
5、执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。