innodb引擎特性

1.Double write

这个特性,主要是为了保证数据的持久性或者说是可靠性。

为什么会有这个特性的出现。主要的原因是。内存中,最小的单元是什么?bit,0和1。但是磁盘上哪?对于MySQL来说,是页。

也就是说,在往磁盘中写数据的时候,如果一个16k的页,你写到8k的时候,掉电了,或者mysql挂了。你数据是不是就乱了。页损坏了,这个MySQL实例毁了。

以上这种情况被叫做 partialwrite。

所以double write就是为了保证数据的可靠性,或者说是保证一个页能安全的写入或者回滚掉。

另外可能会有同学觉得,我有redo log呀。我的页能用redo log保证他是没问题的。

其实这种想法有偏差。就像我刚刚的例子,我16k的页,写入了8k。这种情况下,这个页其实叫corrupt page。怎么判断一个页是不是corrupt页。很简单,我之前的文章有提到过,page header和page trailer这个概念。我还说过这两个地方都保留着lsn。只要这个两个地方是不同的。那么说明,这个页是corrupt的。这种情况下,redo log已经没用了。redo log用来恢复数据一定是页是干净的。也就是说没有corrupt page的存在。

 

我们来看看double write的工作流程。

 

 

 

这个page是128个页顺序写入的。128个页或许说法上有点问题,总之要把这2M给占满。

它整体就是先把脏页写入double write buffer中。然后这个buffer先写到共享表空间,这个速度很快,因为是顺序写入的。

然后buffer再向ibd文件写入。如果在第一次写入时,crash了,ibd的页是干净的,能通过redo log进行恢复。如果在第二次写入时crash了,那么能直接从共享表空间recovery。

通常,double write的开销是5%-20%左右。这个参数不用管,他默认打开了,也没人会把他关掉。除非你的文件系统支持atomic write,不存在partial write的情况。比如zfs或者btrfs。或者你用了fusion io这种超级高端的存储。

当然99%的情况不用去调这个参数。因为没人会用这两个文件系统(这两种文件系统上不了生产,用于实验多)。99%的公司也买不起这种存储。

 

 

2.change buffer

这个功能一句话总结。增强IO性能。

insert buffer:提高second index的插入性能。基本上second index的插入都是随机写。除了一种情况,就是你的二级索引是时间类型的。

他的工作原理是:

1.判断你要插入的页是否在缓冲池中,如果在,直接插入。

2.如果不在,就先将对象放入insert buffer中。这也是一颗b+树,每次最多缓存2k的记录。这个b+树也是有落盘的,不用担心会丢数据。

3.当需要的second index被加载到缓冲池,则将insert buffer中该页的记录进行合并。

你show engine innodb status\G找到insert buffer and adaptive hash index

有个merged recs和merges。两者相减就是你节省的IO。

delete和purge就不多说了,意思是一样的。

相关参数也不用修改,保持默认就行了。

 

3.adaptive hash index

首先,这个参数建议关闭。

然后我们再来聊这个玩意。

首先,我们定位到一条记录,是需要多少时间复杂度。

很多人的回答是O(n),n是树高。

其实是错误的,这个只能定位到记录所在的页。而不能定位到准确的记录。定位到记录还需要去页中的row offset做二分查找。

AHI就是在内存中,构建一个页中的hash索引。这样就能保证,页内查询时间复杂度为O(1).

而,为什么网上都说要关闭这个功能。

因为这个功能其实很矛盾。AHI构建的前提是某一页被频繁访问,被MySQL认定为是热点表。然后再给他加AHI,但是一个页被频繁访问,那说明他的增删改查很频繁,你页内数据都变了,拿维护AHI的代价就更高了。也就是是,你原本节省的资源,被AHI本身使用了。而且AHI的内存是向BP申请的,不是向OS申请的。

而什么情况下mysql会认为这个页是热点页。1.这个索引被访问了17次。2.这个索引中某个页已经被访问了100次。3.对页的访问模式一样。或者是sql指纹是一样的。

这也就是为什么你show engine innodb status\G。有可能lru list + free list不等于总的page数。可能就给hash index用了。

 

4.flush neighbor page

这个参数之前就说过,ssd的情况下关了就行了。

之前我们说过区这个概念,就是最小的分配单元,1M。这个区中的页就是连续的。所以MySQL想的是如果我要刷一个脏页,但是在同一个区中,可能有其他脏页。那就一起刷了。

也就是说,16k -1m。落盘的范围到了这么大。

posted @ 2022-06-28 15:12  拿什么救赎  阅读(36)  评论(0编辑  收藏  举报