(以innodb存储引擎为例)
一、几个基本知识介绍
1.InnoDB有一种缓冲池的技术,将磁盘读到的页放到一块内存区域中。
我们读取数据时,并不是只将满足条件的数据加载到内存中,而是一块数据(局部性原理,我们需要的数据的附近的数据也有可能在未来会被读取),也就是数据页;
页是一个存储引擎从磁盘读取数据到内存的最小单位;
2.脏页
修改数据的时候,会先修改内存缓冲区(buffer pool)里面的页;内存的数据页和磁盘数据不一致,即为脏页。
3.刷脏
将缓冲区的数据写入磁盘(每隔一段时间,一次性完成多个修改)
4.重做日志 redo log
为防止数据库宕机、一些刷脏操作未能执行造成的数据丢失,InnoDB会将所有对数据页的修改操作专门写入redo log(数据来自buffer pool缓冲区)。
疑问:写入redolog也是对磁盘进行操作,为什么不直接写入db文件,而要先写日志再写数据文件?
原因:
刷盘是随机I/O,它会一次次的找到我们需要修改的数据并完成修改,速度缓慢;
而redolog记录的是“在数据页上做了什么修改”,如果我们找到了第一条要修改的数据,那么后面我们所需的数据一定在这条数据的后面,这也是顺序I/O。
优点:A.延迟刷盘时机,提升系统的吞吐量;B.崩溃恢复。
其他特点:
-redo log是物理日志,记录的是“在某个数据页上做了什么修改”;
-循环写,空间固定会用完,用完后覆盖之前完成的记录。
5.undo log
记录事务发生之前的数据状态(如果修改数据时出现异常,可以用undo log来实现回滚操作)
6.归档日志 bin log
记录所有的DDL和DML语句,可用于主从复制和数据恢复:
A.用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。
B.用于数据库的基于时间点的还原。 (每日备份的数据库+bin log完成数据恢复)
逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
二、更新语句的执行过程简述
1.先从内存或者磁盘中拿到这条数据;
2.执行器对数据状态进行修改;
3.将原来的数据状态记录到undo log;
4.调用存储引擎的API接口,在内存(buffer pool)中更新数据状态;并且,将修改后的数据记录到redo log,此时redo log进入prepare状态,并告知执行器;
5.执行器收到通知后记录binlog,并把 binlog 写入磁盘;
6.调用存储引擎接口,设置redo log为commit状态。更新完成。
注:当对应事务的脏页写入到磁盘之后,redo log的使命也就完成了,重做日志占用的空间就可以重用(被覆盖)。
有理解错误的地方,望留言指正,谢谢!