更新语句会讲1.基础架构:查询语句如何执行中查询语句的执行流程同样走一遍。
不过在查询缓存那一块会清空对应表的查询缓存。而且更新的过程中还涉及了两个重要的日志模块:redo log(重做日志)和binlog(归档日志)。
binlog
首先我们要知道mysql是可以将数据恢复到半月以内任意一秒的状态。便是依赖binlog完成的。
备份系统定期对数据库做整库备份,可以一天一备,或者一周,取决于系统的重要性。而binlog则是记录了对数据库的更新记录。
将备份理解成一次快照,binlog记录着所有的逻辑操作,那么我们要将数据库恢复到某个时间点的状态,就只要将找到最近的一次备份,然后从备份的时间点开始,从binlog中取出逻辑操作进行重访到想要恢复的时间点即可。
redo log
首先明确一点,redo log是innodb引擎所独有的。它的作用其实更加类似于缓存。
对于每一次的更新操作如果都要写入磁盘,那么更新的效率也就太低了。为了提高效率就引入的redo log,每次更新将记录写入redo log,然后更新内存就算完成了。等空闲的时候再将更新写入磁盘。
innodb的redo log是固定大小的,比如4个1GB的文件,从头开始写,写到末尾就回到开头重新写。
write_pos是当前记录到redo log中的位置,checkpoint是已经更新到磁盘中的位置。只要write_pos和checkpoint还有空间,就可以继续写redo log,反之的话就需要先推进checkpoint,空出空间才能后继续写。
有了redo log可以保证就算数据库异常重启,提交的更新也不会丢失,称之为crash-safe。
两个日志的不同
redo log是innodb引擎独有的,而binlog是server层的日志。
因为binlog只能用于归档,没有crash-safe的功能。所以innodb引入redo log来实现crash-safe功能。 两者之间的不同可以总结一下:
- binlog是server层的日志,所有引擎都可以使用。redo log是innodb引擎特有的。
- redo log记录的是物理日志,在哪个数据页上进行了什么操作。binlog记录的是逻辑日志,比如给“ID=2这一行的c字段加1”。
- redo log循环写,空间固定会用完。binlog追加写,并不会覆盖以前的日志。
日志两阶段提交
- 进行更新操作的时候,在调用引擎接口写入数据的时候,innodb引擎会将更新操作记录到redo log当中,此时的redo log处于prepare状态。然后告知执行器,执行完毕,随时可以提交事务了。
- 执行器生成这个操作的binlog,并把binlog写入磁盘。
- 执行器调用提交事务的接口,引擎将刚刚写入的redo log变为提交状态。
之所以需要两阶段提交是因为binlog和redo log是两个独立的逻辑,要保证两者之间的一致,就自然需要两阶段提交了。
如果没有两阶段提交,在写两个日志的中间mysql异常重启,就会出现如下的情况。
- 先写redo log后写binlog。那么binlog中就会少一条记录,如果后续需要使用这个binlog恢复数据库的话,就会少一次更新。
- 先写binlog后写redo log,那么binlog就会比实际的数据库状态多一条记录,用这个binlog进行恢复数据库的话就会导致与原数据库的状态不一致。