1 InnoDB存储引擎

InnoDB存储引擎最早由Innobase Oy公司开发(属第三方存储引擎)。从MySQL 5.5版本开始作为表的默认存储引擎。该存储引擎是第一个残缺反对ACID事务的MySQL存储引擎,特点是行锁设计、反对MVCC、反对外键、提供一致性非锁定读,非常适合OLTP场景的利用应用。目前也是利用最宽泛的存储引擎。

InnoDB存储引擎架构蕴含内存构造和磁盘构造两大部分,总体架构图如下:

8.0版本:

[]()

5.5版本:

[]()

2 InnoDB 存储构造

2.1 磁盘构造

2.1.1 表空间 Tablespaces

InnoDB存储引擎的逻辑存储构造是将所有的数据都被逻辑地放在了一个空间中,这个空间中的文件就是理论存在的物理文件(.ibd文件),即表空间。默认状况下,一个数据库表占用一个表空间,表空间能够看做是InnoDB存储引擎逻辑构造的最高层,所以的数据都寄存在表空间中,例如:表对应的数据、索引、insert buffer bitmap undo信息、insert buffer 索引页、double write buffer files 等都是放在共享表空间中的。

表空间分为零碎表空间(ibdata1文件)(共享表空间)、长期表空间、惯例表空间、Undo表空间和file-per-table表空间(独立表空间)。零碎表空间又包含双写缓冲区(Doublewrite buffer)、Change Buffer等

1.零碎表空间 System Tablespace

零碎表空间能够对应文件系统上一个或多个理论的文件,默认状况下, InnoDB会在数据目录下创立一个名为.ibdata1,大小为 12M的文件,这个文件就是对应的零碎表空间在文件系统上的示意。这个文件是能够自扩大的,当不够用的时候它会本人减少文件大小。须要留神的一点是,在一个MySQL服务器中,零碎表空间只有一份。从MySQL5.5.7到MySQL5.6.6之间的各个版本中,咱们表中的数据都会被默认存储到这个零碎表空间。

show variables like '%innodb_data_file_path%'

[]()

2.独立表空间

在MySQL5.6.6以及之后的版本中, InnoDB并不会默认的把各个表的数据存储到零碎表空间中,而是为每一个表建设一个独立表空间,也就是说咱们创立了多少个表,就有多少个独立表空间。应用独立表空间来存储表数据的话,会在该表所属数据库对应的子目录下创立一个示意该独立表空间的文件,文件名和表名雷同,只不过增加了一个.ibd的扩展名而已。

show variables like '%innodb_file_per_table%'

[]()

独立表空间只是存放数据、索引和插入缓冲Bitmap页,其余类的数据如回滚(undo)信息、插入缓冲索引页、零碎事务信息、二次写缓冲等还是寄存在原来的零碎表空间。

3.其余类型的表空间

随着MySQL的倒退,除了上述两种表空间之外,当初还新提出了一些不同类型的表空间,比方通用表空间 (general tablespace)、undo表空间(undo tablespace)、长期表空间(temporary tablespace)等

4.表空间结构

表空间又由段(segment)、区( extent)、页(page)组成,页是InnoDB磁盘治理的最小单位。在咱们执行sql时,不论是查问还是批改,mysql 总会把数据从磁盘读取内内存中,而且在读取数据时,不会独自加在一条数据,而是间接加载数据所在的数据页到内存中。表空间实质上就是一个寄存各种页的页面池。

[]()

「页」是InnoDB治理存储空间的根本单位,也是内存和磁盘交互的根本单位。也就是说,哪怕你须要1字节的数据,InnoDB也会读取整个页的数据,InnoDB有很多类型的页,它们的用途也各不相同。比方:有寄存undo日志的页、有寄存INODE信息的页、有寄存Change Buffer信息的页、寄存用户记录数据的页(索引页)等等。

InnoDB默认的页大小是16KB,在初始化表空间之前能够在配置文件中进行配置,一旦数据库初始化实现就不可再变更了。

SHOW VARIABLES LIKE 'innodb_page_size'

[]()

2.1.2 重写日志 redo log文件

redo log记录数据库的变更,数据库解体后,会从redo log获取事务信息,进行零碎复原。redo log在磁盘上体现为ib_logfile0和ib_logfile1两个文件。MySQL会在事务的提交前将redo日志刷新回磁盘。

在同一时间提交的事务,会采纳组提交(group commit)的形式一次性刷新回磁盘。从而防止一个事务刷新一次磁盘,进步性能。

2.1.3 Double Write Files 双写缓冲文件

double write 是保障 InnoDB 存储引擎操作数据页的可靠性。double write 分为两局部组成,一部分在内存中的 double write buffer, 大小为 2MB,另一部分是物理磁盘上共享表空间中间断的128个数据页,即2个区大小(同样是2MB)。

[]()

2.2 内存构造

InnoDB存储引擎是基于磁盘存储的,并将其中的记录依照页的形式进行治理,因而可将其视为基于磁盘的数据库系统(Disk-base Database)。在数据库中CPU速度与磁盘速度是有很大差距的,基于磁盘的数据库系统通常应用缓冲池技术来进步数据库的整体性能。构造如图所示:

[]()

2.1.1 缓存池 Buffer Pool

Buffer Pool是InnoDB内存中的一块占比拟大的区域,通过内存的速度来补救磁盘速度慢对数据库性能的影响。在数据库中进行读取页的操作,首先将从磁盘读到的页放在缓冲池中,这个过程称为将页”FIX”在缓冲池中,下次再读到雷同的页时,首先判断该页是否在缓冲池中,若在缓冲池中,间接读取该页,否则读取磁盘上的页。

对于数据库中的页的批改操作,首先批改在缓冲池中的页,而后再以肯定频率刷新到磁盘上,这里须要留神的是,页从缓冲池刷新回磁盘的操作并不是在每次页产生更新时触发,而是通过一种称为Checkpoint的机制刷新回磁盘。

缓存区缓存的数据页类型有:索引页,数据页,undo页,插入缓冲(change buffer),自适应哈希索引(adaptive hash index),InnoDB存储锁信息(lock info),数据字典信息(data dictionary)。数据页和索引页占据了缓冲池很大部分。

InnoDB1.0.x版本开始,容许有多个缓冲池实例,每个页依据哈希值平均分配到不同缓冲池的实例中,这样能够缩小数据库外部资源竞争,减少数据库的并发解决能力。

show variables like 'innodb_buffer_pool_instances'

[]()

整个Buffer Pool的阐明用一张图来概括如下:

[]()

1.LRU List,Free List和Flush List——治理InnoDB内存区域

为了缓存治理的效率,缓冲池被实现为页链表,采纳三个链表保护内存页,而内存页也因而对应 3 种状态: Free 尚未应用; Clean 已应用但未修改; Dirty(脏页)已批改;Free页只位于Free List,而Clean和Dirty页同时位于LRU List,Dirty页只存在于Flush List;

[]()

1)LRU List:

数据库中的缓冲池是通过LRU(Latest Recent Used,最近起码应用)算法来进行治理的。即最频繁应用的页在LRU列表的前端,而起码应用的页在LRU列表的尾端。当缓冲池不能寄存新读取到的页时,将首先开释LRU列表中尾端的页。

在InnoDB存储引擎中,缓冲池中页的大小默认为16KB,同样应用LRU算法对缓冲池进行治理。稍有不同的是InnoDB存储引擎对传统的LRU算法做了一些优化。在InnoDB的存储引擎中,LRU列表中还退出了midpoint地位。新读取到的页,尽管是最新拜访的页,但并不是间接放入到LRU列表的首部,而是放入到LRU列表的midpoint地位。这个算法在InnoDB存储引擎下称为midpoint insertion strategy。在默认配置下,该地位在LRU列表长度的5/8处。

[]()

SHOW VARIABLES LIKE'innodb_old_blocks_pct'

[]()

参数innodb_old_blocks_pct默认值为37,示意新读取的页插入到LRU列表尾端的37%的地位(差不多3/8的地位)。在InnoDB存储引擎中,把midpoint之后的列表称为old列表,之前的列表称为new列表。能够简略地了解为new列表中的页都是最为沉闷的热点数据

  • 那为什么不采纳奢侈的LRU算法,间接将读取的页放入到LRU列表的首部呢?

这是因为若间接将读取到的页放入到LRU的首部,那么某些SQL操作可能会使缓冲池中的页被刷新出,从而影响缓冲池的效率。常见的这类操作为索引或数据的扫描操作。这类操作须要拜访表中的许多页,甚至是全副的页,而这些页通常来说又仅在这次查问操作中须要,并不是沉闷的热点数据。如果页被放入LRU列表的首部,那么十分可能将所须要的热点数据页从LRU列表中移除,而在下一次须要读取该页时,InnoDB存储引擎须要再次拜访磁盘。

  • 解决热点数据被移除LRU列表

InnoDB存储引擎引入了另一个参数来进一步治理LRU列表,这个参数是innodb_old_blocks_time,用于示意页读取到mid地位后须要期待多久才会被退出到LRU列表的热端,通过这个办法尽可能使LRU列表中热点数据不被刷出。

SHOW VARIABLES LIKE'innodb_old_blocks_time'

[]()

当有新的数据从磁盘查问到内存时,会写入到 old sub list 的头部,当此数据再次被查问的时候,即在 old sublist 中命中之后,才会放入 new sublist 的头部。当页从LRU列表的old局部退出到new局部时,称此时产生的操作为page made young;如果因为innodb_old_blocks_time的设置导致页没有从old局部挪动到new局部的操作,称为page not made young。
通过命令SHOW ENGINE INNODB STATUS能够察看到如下内容:

SHOW ENGINE INNODB STATUS----------------------BUFFER POOL AND MEMORY----------------------Total large memory allocated 137428992Dictionary memory allocated 10620037Buffer pool size   8191  // 示意以后缓冲池中内存页的数量,内存池的大小=Buffer pool size*16KBFree buffers       1025  //示意以后FREE列表中页的数量;Database pages     6985  //LRU列表中页的数量;Old database pages 2558  //Modified db pages  0     //显示了脏页的数量;Pending reads      0Pending writes: LRU 0, flush list 0, single page 0Pages made young 4656751, not young 61021911  //示意是否产生了页在LRU队列上的挪动;0.00 youngs/s, 0.00 non-youngs/s   //示意每秒两类操作产生的次数;Pages read 1036977, created 686192, written 212430710.00 reads/s, 0.00 creates/s, 0.28 writes/s//示意缓冲池的命中率,失常状况下命中率如果低于95%,则须要察看是否因为全表扫描引起了LRU队列被净化的问题Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000 Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/sLRU len: 6985, unzip_LRU len: 0I/O sum[17]:cur[0], unzip sum[0]:cur[0]

[]()

  • 页压缩性能

InnoDB存储引擎从1.0.x版本开始反对压缩页的性能,行将本来16KB的页压缩为1KB、2KB、4KB和8KB。而因为页的大小产生了变动,LRU列表也有了些许的扭转。对于非16KB的页,是通过unzip_LRU列表进行治理的,LRU中的页蕴含了unzip_LRU列表中的页。

对于压缩页的表,每个表的压缩比率可能各不相同。可能存在有的表页大小为8KB,有的表页大小为2KB的状况。unzip_LRU是怎么从缓冲池中分配内存的呢?

首先,在unzip_LRU列表中对不同压缩页大小的页进行别离治理。其次,通过搭档算法进行内存的调配。例如对须要从缓冲池中申请页为4KB的大小,其过程如下:

  • 查看4KB的unzip_LRU列表,查看是否有可用的闲暇页;
  • 若有,则间接应用;
  • 否则,查看8KB的unzip_LRU列表;
  • 若可能失去闲暇页,将页分成2个4KB页,寄存到4KB的unzip_LRU列表;
  • 若不能失去闲暇页,从LRU列表中申请一个16KB的页,将页分为1个8KB的页、2个4KB的页,别离寄存到对应的unzip_LRU列表中。

2)Free List:

free list 定义是以后没有被应用的内存页,也就是闲暇的内存页,当执行查问操作时,如果页曾经在 buffer pool 中了,则查问到间接返回,如果没有在 buffer pool,并且 free list 不为空,则会从磁盘中查问对应的数据,放入 free list 的某一页中,并且把这页从 free list 中移除,放入 LRU 队列中。Flush List中的脏页在执行了刷盘操作后会将空间还给Free List,通过这种形式能够解决空间碎片化

LRU列表用来治理曾经读取的页,但当数据库刚启动时,LRU列表是空的,即没有任何的页。这时页都寄存在Free列表中。当须要从缓冲池中分页时,首先从Free列表中查找是否有可用的闲暇页,若有则将该页从Free列表中删除,放入到LRU列表中。否则,依据LRU算法,淘汰LRU列表开端的页,将该内存空间调配给新的页。

从下面能够看出 【SHOW ENGINE INNODB STATUS】 :

  • Free buffers示意以后Free列表中页的数量,Database pages示意LRU列表中页的数量。可能的状况是Free buffers与Database pages的数量之和不等于Buffer pool size。因为缓冲池中的页还可能会被调配给自适应哈希索引、Lock信息、Change Buffer等页,而这部分页不须要LRU算法进行保护,因而不存在于LRU列表中。
  • pages made young显示了LRU列表中页挪动到前端的次数,youngs/s、non-youngs/s示意每秒这两类操作的次数。
  • 这里还有一个重要的察看变量——Buffer pool hit rate,示意缓冲池的命中率,通常该值不应该小于95%。若产生Buffer pool hit rate的值小于95%这种状况,用户须要察看是否是因为全表扫描引起的LRU列表被净化的问题。

3)Flush List:

在LRU列表中的页被批改后,称该页为脏页(dirty page),即缓冲池中的页和磁盘上的页的数据产生了不统一。这时数据库会通过CHECKPOINT机制将脏页刷新回磁盘,而Flush列表中的页即为脏页列表。须要留神的是,脏页既存在于LRU列表中,也存在于Flush列表中。LRU列表用来治理缓冲池中页的可用性,Flush列表用来治理将页刷新回磁盘,二者互不影响。

Flush List中的脏页在执行了刷盘操作后会将空间还给Free List。

同LRU列表一样,Flush列表也能够通过命令SHOW ENGINE INNODB STATUS来查看,后面例子中Modified db pages 就显示了脏页的数量。

2.Checkpoint技术

数据库在产生增删查改操作的时候,都是先在buffer pool中实现的,为了进步事物操作的效率,buffer pool中批改之后的数据,并没有立刻写入到磁盘,这有可能会导致内存中数据与磁盘中的数据产生不统一的状况。

假使每次一个页的变动,就将新页的版本刷新到磁盘,那么这个开销是十分大的,若热点数据集中在某几个页中,那么数据库的性能就会变得十分差。同时,如果在从缓冲池将页的的新版本刷新到磁盘时产生了宕机,那么数据就不能复原了,为了防止这种状况,以后事务数据库系统广泛都采纳了Write Ahead Log策略,即当事务提交时,先写重做日志,再批改页,当因为产生宕机而导致数据失落时,能够通过重做日志来实现数据的复原。这也是事务ACID中D(Durability持久性)的要求。

checkpoint的作用:

  • 缩短数据库的复原工夫
  • 缓冲池不够用时,将脏页刷新到磁盘
  • 重做日志不可用时,刷新脏页
    checkpoint的分类
  • sharp checkpoint:在敞开数据库的时候,将buffer pool中的脏页全副刷新到磁盘中。
  • fuzzy checkpoint:数据库失常运行时,在不同的机会,将局部脏页写入磁盘,进刷新局部脏页到磁盘,也是为了防止一次刷新全副的脏页造成的性能问题。

2.2.2 写缓冲 Change Buffer

在MySQL5.5之前,叫插入缓冲(Insert Buffer),只针对INSERT做了优化;当初对DELETE和UPDATE也无效,叫做写缓冲(Change Buffer)。它是一种利用在非惟一一般索引页(non-unique secondary index page)不在缓冲池中,对页进行了写操作,并不会立即将磁盘页加载到缓冲池,而仅仅记录缓冲变更(Buffer Changes),等将来数据被读取时,再将数据合并(Merge)复原到缓冲池中的技术。写缓冲的目标是升高写操作的磁盘IO,晋升数据库性能。

数据的批改分为两个状况:

1.当批改的数据页在缓冲池时

上文讲过,通过LRU、Flush List的治理,数据库不是间接写入磁盘中,是先将redo log写入到磁盘,再通过checkpoint机制,将这些“脏数据页”同步地写入磁盘,等于是将这期间产生的n次的落盘合并成了一次落盘。因为有redo log是落盘的,所以即便数据库解体,缓存中的数据页全副失落,也能够通过redo log将这些数据页找回来。

redo log是数据库用来在解体的时候进行数据恢复的日志,redo log的写入策略能够通过参数管制,并不一定是每一次写操作之后立刻落盘redo log,在局部参数下,redo log可能是每秒集中写入一次,也有可能采取其余落盘策略,然而无论采纳什么形式,redo log的量都是不会缩小的,与数据写入的覆盖性不同,后一条redo log是不会笼罩前一条的,而是增量模式的,因而写redo log的操作,等同于是对磁盘某一小块区域的程序I/O,而不像数据落盘一样的随机IO在磁盘里写入,须要磁盘在多个中央挪动磁头。所以redo log的落盘是IO操作当中耗费较少的一种,比数据间接刷回磁盘要优很多。

2.当批改的数据页不在缓冲池时,不必写缓冲至多须要上面的三步:

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

在没有命中缓冲池的时候,至多多产生一次磁盘IO,对于写多读少的业务场景,性能损耗是很高的

退出写缓冲优化后,流程优化为:

  • 在写缓冲中记录这个操作,一次内存操作;
  • 写入redo log,一次磁盘程序写操作;

其性能与这个索引页在缓冲池中,相近。

3.如何保证数据的一致性?

  • 数据库异样奔溃,可能从redo log中复原数据;
  • 写缓冲不只是一个内存构造,它也会被定期刷盘到写缓冲零碎表空间;
  • 数据读取时,有另外的流程,将数据合并到缓冲池;

下一次读到该索引页:

  • 载入索引页,缓冲池未命中,这次磁盘IO不可避免;
  • 从写缓冲读取相干信息;
  • 复原索引页,放到缓冲池LRU和Flush里;(在真正被读取时,才会被加载到缓冲池中)

4.为什么写缓冲优化,仅实用于非惟一一般索引页呢?

InnoDB里有汇集索引(Clustered Index))和一般索引(Secondary Index)两种。如果索引设置了惟一(Unique)属性,在 进行批改操作 时, InnoDB必须进行唯一性查看 。也就是说, 索引页即便不在缓冲池,磁盘上的页读取无奈防止(否则怎么校验是否惟一!?)

此时就应该间接把相应的页放入缓冲池再进行批改。

5.除了数据页被拜访,还有哪些场景会触发刷写缓冲中的数据呢?

  • 有一个后盾线程,会认为数据库闲暇时;
  • 数据库缓冲池不够用时;
  • 数据库失常敞开时;
  • redo log写满时;(简直不会呈现redo log写满,此时整个数据库处于无奈写入的不可用状态)

6.什么业务场景,适宜开启InnoDB的写缓冲机制?

  • 数据库大部分是非惟一索引;
  • 业务是写多读少,或者不是写后立即读取;

[]()

SHOW VARIABLES LIKE 'innodb_change_buffer_max_size'

[]()

2.2.3 自适应散列索引 Adaptive Hash Index

自适应哈希索引用于优化对BP数据的查问。InnoDB存储引擎会监控对二级索引数据的查找,如果察看到建设哈希索引能够带来速度的晋升(最近间断被拜访三次的数据),则建设哈希索引,自适应哈希索引通过缓冲池的B+树结构而来,因而建设的速度很快。InnoDB存储引擎会主动依据拜访的频率和模式来为某些页建设哈希索引。(在高负载零碎下AHI容易产生资源的争用,进而引起一些bug导致系统受影响甚至解体,故倡议敞开该性能)

2.2.4 重做日志缓冲区 rodo Log Buffer

重做日志缓冲区,当在MySQL中对InnoDB表进行数据更改时,这些更改首先存储在InnoDB日志缓冲区的内存中,而后再写入重做日志(redo logs)的InnoDB日志磁盘文件中。他让MySQL在解体的时候具备了复原数据的能力,即在数据库发生意外的时候,能够进行数据恢复;

日志缓冲区log buffer是内存存储区域,用于保留要写入磁盘上的日志文件的数据。日志缓冲区大小由innodb_log_buffer_size 变量定义,默认大小为16MB。

日志缓冲区的内容定期刷新到磁盘。较大的日志缓冲区能够运行大型事务,而无需在事务提交之前将重做日志数据写入磁盘。因而,如果有更新,插入或删除许多行的事务,则减少日志缓冲区的大小能够节俭磁盘I/O。

这里还波及到一个参数 innodb_flush_log_at_trx_commit :管制如何将日志缓冲区的内容写入并刷新到磁盘,默认为1,不倡议批改

  1. 参数为0时,示意事务commit不立刻把 redo log buffer 里的数据刷入磁盘文件的,而是依附 InnoDB 的主线程每秒(此工夫由参数innodb_flush_log_at_timeout管制,默认1s)执行一次刷新到磁盘。此时可能你提交事务了,后果 mysql 宕机了,而后此时内存里的数据全副失落。
  2. 参数为1时,示意事务commit后立刻把 redo log buffer 里的数据写入到os buffer中,并立刻执行fsync()操作
  3. 参数为2时,示意事务commit后立刻把 redo log buffer 里的数据写入到os buffer中,但不立刻fsync()SQL执行过程

[]()

什么是binlog

binlog是一个二进制格局的文件,用于记录用户对数据库更新的SQL语句信息,默认状况下,binlog是二进制格局的,不能应用文本工具的命令进行查看,而是应用mysqlbinlog解析查看。

binlog的性能

当数据写入到数据库的时候,会同时把更新的SQL语句写入到相应的binlog文件外面,同时在应用mysqldump进行备份的时候,只是对一段时间的数据进行了全局备份,然而如果备份后发现数据库服务器产生故障,这个时候就要用到binlog日志了。

binlog和redolog的区别:

  1. redo log是在InnoDB存储引擎层产生,而binlog是mysql数据库的下层产生,而且binlog是二进制格局的日志,不仅仅针对InnoDB存储引擎。
  2. 两种日志记录的内容模式不同,MySQL的binlog是逻辑日志,而InnoDB存储引擎层面的重做日志是物理日志。
  3. 两种日志与记录写入磁盘的工夫点不同,二进制日志只在事物提交实现后进行一次写入,而redo log的重做日志在事物的进行过程中一直地被写入。
  4. binlog不是循环应用,在写满或者重启之后,会生成新的binlog文件,然而redo log是循环应用的。

3 InnoDB 存储个性

  1. 写缓冲 Change Buffer
  2. 两次写 Double Write

InnoDB在把Dirty 脏页写回到表空间之前,在内存中会线拷贝到间断的内存空间double write buffer缓冲区,而后再把它们写到一个叫doublewrite buffer file的间断磁盘存储区域内,在写doublewrite buffer file实现后,InnoDB才会把Dirty pages写到data file的适当的地位。如果在写page的过程中发生意外解体,InnoDB在稍后的复原过程中在doublewrite buffer file中找到完整的page正本用于复原。

[]()

为什么须要双写?

InnoDB 的Page Size个别是16KB,其数据校验也是针对这16KB来计算的,将数据写入到磁盘是以Page为单位进行操作的。而计算机硬件和操作系统,写文件是以4KB(512字节)作为单位的,不能保障MySQL数据页面16KB的一次性原子写。试想,在某个Dirty Page flush的过程中,产生了零碎断电(或者OS解体),16K的数据只有局部被写到磁盘上,只有一部分写是胜利的,这种景象被称为partial page writes。在呈现磁盘解体的时候,InnoDB 引擎会从共享表空间中的doublewrite找到该页的一个正本,将其复制到表空间文件,再利用重做日志,保障 InnoDB 存储引擎操作数据页的可靠性。

为什么不能应用redo log 解决partial page writes?

一旦partial page writes产生,那么在InnoDB复原时就很难堪:redo log的页大小个别设计为512个字节,因而redo log page自身不会产生break page。用redo log来解决partial write 实践上是可行的,不过innodb的redo log是物理逻辑日志,并不是纯物理日志,因而产生partial write后解体复原过程中不能间接利用redo log ,innodb发现break page后实际上会报错。物理逻辑日志不是齐全幂等的,这取决于重做日志类型,对于INSERT产生的日志其不是幂等的。

两次写的工作流程

double write由两局部组成,一部分是InnoDB内存中的double write buffer,大小为2MB,另一部分是物理磁盘上的ibdata,零碎表空间中大小为2MB,共128个间断的Page(2*1024/16KB=128),即两个分区(extend)一个段(segment)。其中120个页用于批量刷新脏页(如LRU LIST刷新与FLUSH LIST刷新这两种刷新策略),另外8个页用于单页刷新(Single Page Flush)。做辨别的起因是批量刷脏是后盾线程做的,不影响前台线程。而单页刷新是用户线程发动的,须要尽快的刷脏页并替换出一个闲暇页进去。

InnoDB刷新(写出)缓冲区中的数据页时采纳的是一次写多个页的形式:

  • 多个页就能够先程序写入到double write buffer,并调用fsync()保障这些数据被刷新到double write磁盘(ibdata)。
  • 而后数据页调用fsync()被刷新到理论存储地位;
  • 故障复原时InnoDB查看double write Buffer与数据页原存储地位的内容,若double write页处于页断裂状态,则简略的抛弃;若数据页不统一,则从double write页还原。

因为double write页落盘与数据页落盘在不同的工夫点,不会呈现double write页和数据页同时产生断裂的状况,因而doublewrite技术能够解决页断裂问题,进而保障了重做日志能顺利进行,数据库能复原到统一的状态。

3.自适应哈希索引 Adaptive Hash Index

4 参考资料

掘金小册《MySQL 是怎么运行的:从根儿上了解 MySQL》学习笔记https://www.jianshu.com/p/3394321c11bf

作者:京东物流 邓钧蔚

起源:京东云开发者社区 自猿其说Tech