关于mysql:InnoDB的两点特性

1次阅读

共计 1618 个字符,预计需要花费 5 分钟才能阅读完成。

介绍下插入缓冲 (insert buffer) 与两次写(double write).

插入缓冲
为什么须要插入缓冲?

Innodb 存储引擎中行记录 是依照汇集索引维度顺序存储 的,Innodb 的表也称为索引表;因为行记录只能依照一个维度进行排序,所以一张表只能有一个汇集索引。

在 InnoDB,主键是行惟一标识,通常应用程序中行记录的插入程序是依照主键递增的程序进行插入的,因而,插入汇集索引个别是程序的,不须要磁盘的随机读取。然而对于非汇集索引叶子节点的插入不再是程序的了,次要是因为 B + 树的个性决定了非汇集索引插入的离散性(这里再进一步说明下,非汇集索引的根节点存的是索引列的值,它们是有序的,而根节点下的叶子节存的是主键的值,它们是无序的。又因为行记录是依照汇集索引维度顺序存储的,为了保住插入后的有序性,咱们就必须随机离散地拜访非汇集索引页以找到叶子节点的主键值),这里就须要离散地拜访非汇集索引页,显然,随机读取是会导致插入操作性能降落。

这样,InnDB 设计了 Insert Buffer 性能:对于非汇集索引的插入或更新操作,不是每一次直接插入到索引页中,而是先判断插入的非汇集索引页是否在缓冲池中,若在,则直接插入;若不在,则先放入到一个 Insert Buffer 对象中,而后再以肯定频率和状况进行 Insert Buffer 和辅助索引叶子节点的 merge 操作,这时通常能将多个插入合并到一个操作中,这就大大提高了对于非汇集索引插入的性能。

不过,Insert Buffer 的应用须要同时满足两个条件:

  1. 索引是辅助索引
  2. 索引不是惟一的(数据库并不去查找索引页来判断插入的记录是否惟一,如果进行了判断会有离散读的状况产生)

Change Buffer
Change Buffer 是对 Insert Buffer 的降级。如果没有应用 Change Buffer,要对不在缓冲池里的非惟一索引页进行批改,那流程是怎么的呢?

  1. 先把须要批改的索引页从磁盘加载到缓冲池,一次磁盘随机读操作;
  2. 批改缓冲池中的页,一次内存操作;
  3. 写入 redo log,一次磁盘程序写操作;

能够看到会呈现两磁盘操作(有一次还是随机的), 一次内存操作。那如果应用了 Change Buffer 又是怎么的流程呢?

  1. 在写缓冲中记录这个操作(insert 的操作而非 update 操作),一次内存操作;
  2. 写入 redo log,一次磁盘程序写操作;

换句话就是:对页进行了写操作,并不会立即将磁盘页加载到缓冲池,而仅仅记录缓冲变更 (buffer changes),等将来数据被读取时,再将数据合并(merge) 复原到缓冲池中的技术。写缓冲的目标是升高写操作的磁盘 IO,晋升数据库性能。这里只会呈现一次磁盘的程序操作与一次内存操作,所以性能会很高。
要留神的是,Change Buffer 比拟适宜的业务是写多读少,或者不是写后立即读取。

Double Write
Insert Buffer 对于 InnoDB 来说是性能上的晋升,那 Double Write 则是数据页可靠性的保障。来看张图:

  1. 通过 memcpy 函数将脏页先复制到内存中的 doublewrite buffer。
  2. 通过 doublewrite buffer 分两次,每次 1MB 程序写入共享表空间的物理磁盘上,而后调用 fsync 函数同步磁盘。
  3. 实现 doublewrite buffer 页的写入后,再将 doublewrite buffer 中的页离散写入各个表空间文件中。

如果第 2 步呈现了问题,也就是 doublewrite 写入失败,innodb 会载入磁盘原始数据和 redo 日志比拟,并从新刷到 doublewrite buffer。
如果第 3 步出了问题,innodb 能够从共享表空间中的 doublewrite 中找到该页的一个正本,将其复制到表空间文件,再利用重做日志。

参考的文章:
写缓冲(change buffer),这次彻底懂了!!!
InnoDB 要害个性之 double write
【mysql】Innodb 三大个性之 double write

正文完
 0