一、InnoDB 更新数据得整体架构
每个组件的作用说明:
用一条更新数据来说明每个主键得作用:
update student set name = "zhangsan" where id = 10
innodb得重要内存接口:缓冲池(Buffer Pool)
innodb存储引擎中有一个重要得放在内存中得组件,就是缓冲池(Buffer Pool),这里面会缓存很多得数据,以便于以后查询数据得时候,如果在内存缓冲中有数据,就可以直接从内存返回不需要查询磁盘加载到内存缓冲中。
如果InnoDB存储引擎需要执行一条更新语句得时候,比如上面那条数 id = 10 这条数据时候,首先会在缓冲中是否存在 id = 10 这条数据,如果不存在就直接从磁盘中把该条数据加载到缓冲里来,而且会对这条数据加独占锁。
undo 日志文件:保证更新后的数据可以回滚
假设 id = 10 这行数据的name原来是 zhangsan, 现在需要更新为 lisi,那么此时需要先把更新的原来的值 name = "zhangsan" 和 id = 10 这些信息,写入到undo日志文件中,如果在后面的操作出现异常,需要做回滚数据就会从undo日志文件中加载回滚。
更新Buffer Pool中的缓冲数据
当我们把要更新的那行数据从磁盘文件加载到缓冲池,同时对该行数据枷锁后把更新前的旧值写入到undo日志文件之后,旧可以正式开始更新这行记录了,先更新缓冲池中的记录,此时这行数据是脏数据。因为磁盘上的依旧是 name 的值是zhangsan,内存中的已经是lisi所以说是脏数据。
Redo Log buffer:防止Mysql服务宕机后,保证数据不被丢失。
在buffer pool 中修改了数据后,我们必须把对内存所作的修改写入到一个Redo Log Buffer的内存缓冲区中,这个缓冲区是用于存放redo日志的。所谓的redo日志,就是记录下来对数据做了什么修改,比如对 id = 10 这行记录修改了name字段的值为lisi,这就是一条日志。
在提交事物的时候会将redo日志写入到磁盘中(顺序写入),有一下集中方式写入:
innodb_flush_log_at_trx_commit = 1:不写入磁盘
innodb_flush_log_at_trx_commit = 2:提交事务的时候刷盘
innodb_flush_log_at_trx_commit = 3:写入系统的os再定时刷入磁盘
一般使用的是第二种。
binglong日志
binglog日志是mysql server 服务的日志,叫做归档日志,他里面记录的是逻辑行的日志,类似于 对 srtudent 表中的 id = 10 这行数据做了更新操作,更新后的值是什么。
在提交事务的时候需要binglog日志写入到磁盘中,写入的策略如下:
sync_binglog = 0:提交事务时写入系统缓冲在定时刷入磁盘
sync_binglog = 1:提交事务时写入磁盘。
总结innodb存储引擎做一次跟新的架构原理:
大家通过一次更新数据的流程,就可以清晰地看到,InnoDB存储引擎主要就是包含了一些buffer pool redo log buffer等内存里的缓存数据,同时还包含了一些undo日志文件,redo日志文件等东西,同时mysqlserver自己还有binlog日志文件
在你执行更新的时候,每条SQL语句,都会对应修改buffer pool里的缓存数据、写undo日志、写redo log buffer几个步骤
但是当你提交事务的时候,一定会把redolog刷入磁盘,binloq刷入磁盘,完成redolog中的事务commit标记;最后后台的1O线程会随机的把buffer pool里的脏数据刷入磁盘里去
面试题:
执行更新操作的时候,为什么不精细修改磁盘上的数据?
如果保证msyql服务宕机后数据更新后的数据不丢失?