目录
1.更新数据的流程
1.1执行流程
例如一个更新数据,整个流程如上图所示:
1.从磁盘加载数据到buffer pool,会先去判断要更新的数据所在数据页是否已经被加载到了,如果已经被加载到了buffer pool中的数据页就直接使用。
2.写入数据的旧值到undo log日志中,用于事务回滚。
3.更新buffer pool数据页中内存数据。
4.写入内存中的redo log,这个时候还没写入磁盘中,记录对那个表那条记录做了什么操作。
5.提交事务,将内存的redo log写入磁盘中的redo log日志,用于崩溃恢复。
6.提交事务之前,还要在内存中写binlog日志,提交事务时写入磁盘文件。
7.将commit标记写入redo log,数据最后通过线程写入磁盘整个流程完成。
注意:最后一步是为了让redo log与binlog保持一致。5、6、7三步都执行完成才算提交事务完毕。
1.2 binlog日志
实际上我们之前说的redo log,他是一种偏向物理性质的重做日志,因为他里面记录的是类似这样的东西,“对哪个数据页中的什么记录,做了个什么修改”。而且redo log本身是属于InnoDB存储引擎特有的一个东西。而binlog叫做归档日志,他里面记录的是偏向于逻辑性的日志,类似于“对users表中的id=10的一行数据做了更新操作,更新以后的值是什么”。binlog不是InnoDB存储引擎特有的日志文件,是属于mysql server自己的日志文件。
在更新数据时,我们知道会写undo log、redo log日志,同时还会写binlog日志,和redo log日志一样,先是写在内存中,提交事务时,才会写入磁盘。对于binlog刷盘其实有不同的策略,可以通过sync_binlog参数进行配置,默认为0,查看命令如下:
show variables like 'sync_binlog';
sync_binlog=0时,先将binlog写入内存中,还不是写入磁盘文件,之后线程写入磁盘。写入磁盘前mysql宕机日志会丢失,不安全。
sync_binlog=1时,在提交事务会强制将binlog写入磁盘,日志不会丢失。
1.3 innodb如何保证数据的完整性
(1)在更新完buffer pool中数据页,mysql崩溃宕机了,此时已经写了undo log日志,相当于事务没有完成,回滚数据,那么重启后即可。
(2)在写入redo log、binlog过程中,mysql宕机,相当于事务没有提交完成,此时视为回滚事务,重启mysql执行undo log即可恢复到原来数据。
(3)binlog刷盘参数sync_binlog配置为1,在提交事务会强制将binlog写入磁盘,日志不会丢失。
2.几个链表的使用
mysql数据库在进行CRUD时,buffer pool在运行中会频繁的从磁盘加载数据页到其中,找个过程会配合free链表、flush链表、lru链表使用。
比如把磁盘中的数据页加载到buffer pool中去,会从free链表中移除描述数据块,然后将数据页加载到buffer pool中去,然后lru的冷数据区域的头部放入这个数据页。如果你修改了这个数据页,那么就会在flush链表中记录这个数据页。加载完数据页1秒之后重复使用该数据页,还会把数据页移动到lru链表的热数据页的头部去。更新了数据页最后刷入磁盘,会从flush链表中移除。同时该数据页可能不在使用,又移动到了lru链表的冷数据区,可能没有过空闲的数据页,根据lru算法会淘汰lru冷数据区,这时free链表又会增加空闲的节点。
可以看到整个过程是三个链表配合使用,具体过程比较复杂,需要明白每个链表的作用,已经他们是在什么情况下使用的。多多理解哈。
今天的笔记就到这里啦