2 一条SQL更新语句是如何执行的 - Jokairui/MySQL-in-action-45-episodes GitHub Wiki
Cue
什么是redo log?
什么是binlog?
什么是两阶段提交?
两阶段提交的意义是什么?保证任何情况下binlog和redo log的一致性
MySQL是如何保证crash-safe的?
一条SQL更新语句是如何执行的?
Notes
redo log
-
是InnoDB引擎特有的的日志文件
-
是硬盘上的一组文件,用来记录数据库做了什么修改
-
采用了WAL(Write-Ahead Logging)技术,即先记录redo log,再在内存中作数据的更新,最后在适当的时候,将数据写到硬盘上。
-
可以将redo log想象成一个圆,当redo log写满时,就必须擦除最早的log,同时将这些log所代表的改动写到硬盘上。
-
由于MySQL先写redo log,再更新数据的这个特性,就保证了它crash-safe的这一特性
-
innodb_flush_log_at_trx_commit这个参数推荐设成1,表示每次写redo log都会直接写在磁盘上
binlog
- Server层特有的日志文件
- redo log是物理日志,记录的是“在某个数据页上具体的修改”,binlog是逻辑日志,记录的是SQL语句的原始逻辑——“给ID为2的行的c字段+1“。可以类比为形容一栋房子,物理日志是指”XX栋XX号“,逻辑日志是指”这是Khirye买的房子“
- binlog没有大小限制,可以一直写下去
- sync_binlog推荐设置成1,表示每次事务的binlog都会持久到磁盘上
两阶段提交&UPDATE语句的执行流程
- 执行器通过引擎获取到对应行
- 执行器执行对应操作,例如+1,再调用引擎接口写入这行新数据
- 引擎将改动记录到redo log中,同时在内存中更改了对应的数据,此时redo log便处于prepare状态,表示事务随时可以提交
- 执行器生成这个事务的binlog,并将binlog写入磁盘
- 执行器调用引擎层的提交事务接口,引擎将redo log转变为commit状态,更新完成
两阶段提交的意义
- redo log只有进入commit状态,这个事务才被引擎承认,crash重启后引擎会将redo log中记录的更改写到磁盘上,同时,重启后处于prepare状态的事务会被回滚,对应的binlog也会被回滚掉
- binlog常用的作用有两个,作为备份用来恢复数据库,以及作为数据源拉起从库
Summary
redo log是InnoDB特有的引擎层日志,它的通过WAL机制,保证了MySQL拥有crash-safe的特性;binlog是server层的日志,引擎无关的,它与redo log配合,实现了两阶段提交,保证了数据库从crash恢复的情况下,binlog和redo log的一致性。