1、内存管理
InnoDB作为mysql默认的引擎,它擅长处理事务,具有自动崩溃恢复的特性,在日
常开发中使用非常广泛。InnoDB引擎架构图主要分为内存结构和磁盘结构两大部分
InnoDB存储引擎主要包含表空间、段、区、页、层级关系
Buffer Pool 内存的一块区域,InnoDB在表和索引数据访问时缓。通过配置项:innodb_buffer_pool_size进行配置
,内部以一个个16kb大小的page页构成 用page链表结构将它们组织在一起,交给lru链表管理。
change buffer(把改变的操作缓存起来)(提升语句执行效率)
当需要更新数据页的时候,如果数据页在内存中就直接更新。如果不在内存中 在不影响数据一致性的前提下,innodb会将这些更新操作缓存在change buffer中。在下次查询需要访问这个数据页的时候,将数据页读入内存,然后合并change buffer中与这个页有关的操作 系统也有后台线程会定期合并;change buffer只可以用在普通索引,不可以用在唯一索引上。因为当更新、插入数据的时候,唯一索引需要判断该更改是否在表中满足唯一性约束。也就是必须通过将数据页读取到内存中判断是否存在这条记录。change buffer用的是buffer pool里的内存,可以通过参数innodb_change_buffer_max_size来动态设置,change buffer适合写多读少的场景,因为即使更新语句使用了change buffer机制,减少了更新时的随机读磁盘操作,但是如果查询场景很多 更新完又立刻查询。那么又会立刻触发merge操作,这样随机访问IO的次数不仅不会减少,反而增加了change buffer的维护代价。
Log buffer 由于我们的数据是先写入内存 再由系统flush到磁盘 ,如果缓存中数据更改但是还没来得及持久化到磁盘中,突然断电或者宕机,就会导致已变更的数据丢失。
所以,缓存中的数据每做一次更改,就记录在日志文件中持久化到磁盘,这个日志文件称之为redo log; 由于事务可以回滚操作故需要记录修改前的数据称之为 undo log。undo log 和 redo log 可以用于当缓存中数据丢失的恢复,但是每更改一次就要进行一次IO操作,虽然由随机IO变成了顺序IO 但是仍然很浪费性能 所以就产生了log buffer。log buffer 的持久化策略 可以通过innodb_flush_log_at_trx_commit 参数进行调节。
Double write buffer 由于InnoDB buffer pool是16kb为一页,但是操作系统从内存到磁盘是4kb为一页进行存储的。所以,InnoDB内存中的数据页,要持久化到磁盘中时,需要分成4个4KB的系统页,逐一持久化到磁盘。 但是4个系统页从内存到磁盘并不是原子操作,所以很容易发生InnoDB的数据页刷盘一部分,就发生断电、宕机的情况,这种就会造成 数据页的损坏,且 redo log是无法利用磁盘中“损坏的数据页”,对缓存中数据进行恢复的,于是Doubel write buffer 就应运而生了。
2、写入过程
第1步:先看缓冲区有没有这条数据,如果没有就将要修改的那一行数据所在的一整页加载到缓冲池Buffer Pool中
第2步:将旧值写入undo日志中,便于回滚以及mvcc机制的运作
第3步:将Buffer Pool中的数据更新为新的数据。
第4步:写入redo日志缓冲池。
第5步:准备提交事务前,将redo日志写入磁盘
第6步:准备提交日志前,将binlog日志写入磁盘
第7步:将commit标记写到redo日志中。
第8步:事务提交完成。
第9步:将缓冲区的数据写入磁盘。