WAL
WAL技术,WAL的全称是Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。
具体流程
- 当有一条记录需要更新的时候,InnoDB引擎就会先把记录写到redo log(粉板)里面,并更新内存,这个时候更新就算完成了。
- innoDB引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做,这就像打烊以后掌柜做的事。
redo log
InnoDB的redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB,那么这块“粉板”总共就可以记录4GB的操作。
write pos是当前记录的位置,一边写一边后移,写到第3号文件末尾后就回到0号文件开头。 checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。
有了redo log,InnoDB就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe。
innodb_flush_log_at_trx_commit这个参数设置成1的时候,表示每次事务的redo log都直接持久化到磁盘。这个参数我建议你设置成1,这样可以保证MySQL异常重启之后数据不丢失。
bin log
redo log是InnoDB引擎特有的日志,而Server层也有自己的日志,称为binlog(归档日志)。
两种日志有以下三点不同。
-
redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。
-
redo log是物理日志,记录的是“在某个数据页上做了什么修改”;
binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”。 -
redo log是循环写的,空间固定会用完;
bin log 是可以追加写入的。
追加写”是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
sync_binlog这个参数设置成1的时候,表示每次事务的binlog都持久化到磁盘。
更新语句的执行流程
stateDiagram-v2
查询对应数据行--> 数据页在内存中
state if_state <>
数据页在内存中 --> 从磁盘中读入内存: 否
从磁盘中读入内存 --> 返回行数据
数据页在内存中 --> 返回行数据 : 是
返回行数据 --> 更新操作(N+1)
更新操作(N+1)--> 写入新行
写入新行 --> 新行更新到内存
新行更新到内存 --> 写入redolog,处于prepare阶段
写入redolog,处于prepare阶段 --> 写binlog
写binlog --> 提交事务,处于commit状态
两阶段提交
简单说,redo log和binlog都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。
将redo log的写入拆成了两个步骤:prepare和commit,这就是"两阶段提交"。
不两端提交的结果:
- 写完redolog 后写binlog binlog 缺失 值没变 => 数据不同步
- 写完binlog 后写redolog redolog 丢失 事务无效 => 数据不同步
如果不使用“两阶段提交”,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致。