InnoDB关键特性

插入缓冲

当要插入数据时,对于唯一索引来说:

若索引页在内存的话,则往内存插入。若不在,则先把对应的索引页加载到内存,然后判断是否重,然后插入

对于非唯一索引而言,对应的索引页在内存的话,同上,然后写redo。

而对于不在的情况,则是将“插入xxx数据”记录到insert buffer(其实insert buffer是一个 b+树)里,同时将

写 insert buffer这个行为写一条日志到redo log(此时的redo就不是传统意义上的物理日志),整个操作没

有磁盘IO


change buffer是InnoDB1.0x对insert buffer的升级,扩展了delete buffer(标记删除),purge buffer(真

正删除)。change buffer不仅可以缓冲插入,更改和删除也可以。change buffer位于buffer pool中,大小

由innodb_change_buffer_max_size。默认为25,最多占buffer pool的25%,最大有效值可为50,超50还是

50

insert buffer 里有个bitmap用来追踪每个二级索引页的可用空间

什么时候合并insert pool到真正的二级索引页中?

1. 当二级索引页加载时,通过bitmap发现内存存在了,这时候就会合并
2. 发现二级索引页缓冲的数据占用已经小于1/32,则会强制从磁盘里读数据然后合并数据
3. master Thead 后台线程每10秒一次
4. 数据库正常关闭

什么时候change buffer落盘

1. 数据库空闲时,后台进程落盘
2. 缓冲池不够用了
3. 数据库正常关闭时
4. redo写满了

为什么要把change buffer中的记录写redo

同样也是为了持久化么。当使用到change buffer意味着内存还没有这数据,如果这时候宕机了,数据就没了

这时候做redo就是为了宕机重启后可以恢复内存数据。

当宕机重启时:

先看事务是否提交,无提交直接回滚。提交了就看change buffer是否落盘,有,则直接使用change buffer

恢复数据;没有就通过redo 恢复changbuffer,再通过change buffer恢复数据

可以不使用change buffer,只使用redo记录吗

PS:(虽然说redo log是顺序磁盘IO,某种情况是要比change buffer的随机内存速度快的)。change只是记

录了插入这个操作,并没有真正地插入到真正的索引页上!!!

不行,因为change buffer里维护了insert bit map。用来快速追踪哪些页是需要合并插入缓冲的,当这些页

被加载到内存时,就可以被合并了。如果单靠redo log的话,当被合并的页加载到内存是无法感知的。而且

redo log是循环记载,会被加载到磁盘,也就是写入磁盘前必须** 合并插入缓冲区(因为redo log里有change **

buffer的插入记录),这会加重redo log的负担

Change Buffer = 存着很多“等待插入索引页的记录”
那么“哪些页需要合并”就是 哪些页已经有“待插入的缓存记录”但还没真正写入
合并(Merge) = 把 Change Buffer 中某页的缓存记录,真正插入到该页中。

写了redo log,为什么buffer pool还要落盘?

缓冲池大小有限,如果需要insert的页一直没被加载,insert pool会一直积累,需要落盘腾空间

两次写?

double write由两个部分组成,一个double buffer位于内存,2mb,另外一个位于磁盘上,buffer area上,

同样也是2mb

刷新脏页时,并不是直接把脏页数据直接刷到磁盘对应的表空间,而是先copy到double write buffer。然后

由double write buffer顺序写入double write area(这时候意味着这些页数据已经被持久化了)。然后再从

double write buffer执行fsync 将里的数据刷到各自的表空间,多了两个步骤

1.脏页数据被copy到了double write buffer

2.直接落到各自的表空间前顺序写入到了double write area里

为什么要这么搞?

如果刷脏页,一个脏页16kb,如果写一半宕机了,就会出现磁盘的表数据人不人鬼不鬼的。 有了double

write area后,如果宕机重启后,会检查double write area是否有对应完整页数据,如果有的话就完整恢复

没有的话,则意味着没落盘。(其实细想的话也是一种先写日志的操作)

那么这种丢失能否通过redo恢复?答案是不行!因为redo是物理日志,记录要对页文件进行的物理修改,它记载了:对xx页偏移量500的位置写入aaa、将xx页偏移量650的位置的数据由bbb改为ccc。但现在的问题是,你的页是缺失或者只更改了一部分的!页已经发生了损坏,再对其重做是没有意义的

如果脏页在从内存中的doublewrite buffer 写入到磁盘中的doublewrite 中发生了宕机怎么办?

没有影响,这说明你还没向磁盘中刷新脏页,磁盘中的数据是完整的,宕机重启后可以根据redolog进行数据恢复

为什么要双写

问题 Doublewrite 帮你解决什么?
写盘时崩溃可能导致页“写了一半” 有 Doublewrite 做缓冲区,保证每个页要么完整写入,要么完整回滚
随机写很慢 先顺序写到 doublewrite area → 再随机写本体,提升整体效率

两次写默认打开,可通过innodb_doublewrite关闭

自适应hash索引

InnoDB自动根据访问的频率和模式自动地为某些热点页建立哈希索引

异步IO

刷盘和从磁盘加载页数据都是异步IO,且会根据实际情况进行IO merge,如发现读取的页是连续的,就会连

续读取,而不是一页页读

刷新邻接页:

刷新一个脏页时,会检测该页所在区的所有页,如果是脏页,一起刷新,多次IO合并为一个IO,但可能有以下问题: 是否将不怎么脏的页刷新了?该页很快又变脏了 固态硬盘有较高的IOPS,是否还需要这个特性? 为此,InnoDB1.2.x版本开始提供参数innodb_flush_neighbors决定是否启动该功能,默认为0,不启动