mysql学习之InnoDB

mysql学习之InnoDB(一)

写在前面

InnoDB通过使用多版本并发控制(MVCC)来获得高并发性,并且实现 了SQL标准的4种隔离级别,默认为REPEATABLE级别。同时,使用一 种被称为next-key locking的策略来避免幻读(phantom)现象的产生。 除此之外,InnoDB储存引擎还提供了插入缓冲(insert buffer)二次写 (double write)自适应哈希索引(adaptive hash index)、**预读(read ahead)**等高性能和高可用的功能。上述可以概况的描述为innoDB存储引擎高性能的原因。

一、InnoDB体系架构

innodb存储引擎有多个内存块,可以认为这些内存块组成了一个大的内存池,负责如下工作:

  • 维护所有进程/线程需要访问的多个内部数据结构
  • 缓存磁盘上的数据,方便快速地读取,同时在对磁盘文件的数据修改之前在这里缓存。
  • 重做日志(redo log)缓冲

具体结构如下图所示:
在这里插入图片描述

1.1 后台线程

InnoDB存储引擎是多线程的模型,因此其后台有多个不同的后台线程,负责不同的任务。

  1. Master 线程

    Master Thread 是一个非常核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓存(Insert Buffer)、Undo页的回收等。

    页:表示磁盘和缓冲池页的映射。 脏页表示:页被用户修改了导致两者不一致。
    插入缓存和Undo页下面会介绍
    
  2. IO 线程

    在InnoDB存储引擎中大量使用了AIO(异步io)用来处理写IO的请求,这样可以提高数据库的性能。而IO线程的作用主要是处理这些AIO的回调处理(call back)(异步线程肯定要有回调,表示写完了)。这里也说明了innodb的高效性,大量异步处理,给程序运行预留了大量的cpu时钟,连从内核空间拷贝到用户空间的等待时间都利用aio来优化了。

    其还细分为write、read、insert buffer和log io四种类型。

  3. Purge 线程

    事务提交之后,undolog可能就不在需要了,因此需要purge线程回收已经使用并分配的undo页。早期版本的回收操作是通过Master 线程完成的。为了减轻Master线程的压力出现了purge线程。支持线程的并发运行。

  4. Page Cleaner Thread

    Page Cleaner Thread 是在1.2x版本中诞生的。它负责脏页的刷新。进一步减轻了Master线程的工作,防止阻塞用户查询线程的执行。提高了innodb 的性能。

1.2 内存

1、缓冲池

在数据库系统中,由于CPU速度与磁盘速度之间的鸿沟, 基于磁盘的数据库系统通常使用缓冲池技术来提高数据库的整体性能。

在数据库中进行读取页的操作,首先将从磁盘 读到的页存放在缓冲池中,这个过程称为将页“FIX”在缓冲池中。下一 次再读相同的页时,首先判断该页是否在缓冲池中。若在缓冲池中,称 该页在缓冲池中被命中,直接读取该页。否则,读取磁盘上的页。

对于数据库中页的修改操作,则首先修改在缓冲池中的页,然后再以一 定的频率刷新到磁盘上。这里需要注意的是,页从缓冲池刷新回磁盘的 操作并不是在每次页发生更新时触发,而是通过一种称为Checkpoint的 机制刷新回磁盘。同样,这也是为了提高数据库的整体性能。

对于InnoDB存储引擎而言,其缓冲池的配置通过参数 innodb_buffer_pool_size来设置。

那么缓存池中缓存的数据页类型有哪些呢?

索引页、数据页、undo页、 插入缓冲(insert buffer)、自适应哈希索引(adaptive hash index)、 InnoDB存储的锁信息(lock info)、数据字典信息(data dictionary) 等。

在这里插入图片描述

再V1.0.x版本开始,可以存在多个缓存池实例。根据页的hashcode来进行寻址。提高了数据库的并发能力。

2 LRU List、Free List和Flush List

innoDb引擎如何管理这么大的内存区域?内存如果使用满了如何处理?如果有效的利用固定的内存?

数据库中的缓冲池是通过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处。。midpoint位置可由参数 innodb_old_blocks_pct控制。。在 InnoDB存储引擎中,把midpoint之后的列表称为old列表,之前的列表称 为new列表。可以简单地理解为new列表中的页都是最为活跃的热点数 据。

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

为了解决这个问题,InnoDB存储引擎引入了另一个参数来进一步管理 LRU列表,这个参数是innodb_old_blocks_time(默认为0),用于表示页读取到mid 位置后需要等待多久才会被加入到LRU列表的热端。可以通过设置这个参数为非0使下一次大数据量页fix到内存中不直接变成热点数据,导致原有的热点数据被刷新出缓存。

LRU列表用来管理已经读取的页,但当数据库刚启动时,LRU列表是 的,即没有任何的页。这时页都存放在Free列表中。当需要从缓冲池中 分页时,首先从Free列表中查找是否有可用的空闲页,若有则将该页从 Free列表中删除,放入到LRU列表中。否则,根据LRU算法,淘汰LRU 列表末尾的页,将该内存空间分配给新的页。当页从LRU列表的old部 分加入到new部分时,称此时发生的操作为page made young,而因为 innodb_old_blocks_time的设置而导致页没有从old部分移动到new部分的 操作称为page not made young。可以通过命令SHOW ENGINE INNODB STATUS来观察LRU列表及Free列表的使用情况和运行状态。(show engine innodb status 执行后,会显示一个Buffer pool hit rate,表示缓冲池的命中率,这个例 子中为100%,说明缓冲池运行状态非常良好。通常该值不应该小于 95%。若发生Buffer pool hit rate的值小于95%这种情况,用户需要观察 是否是由于全表扫描引起的LRU列表被污染的问题。 )

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

1.3 重做日志缓冲

InnoDB存储引擎的内存区域除了有缓冲池外,还有 重做日志缓冲(redo log buffer)。InnoDB存储引擎首先将重做日志信 息先放入到这个缓冲区,然后按一定频率将其刷新到重做日志文件。重 做日志缓冲一般不需要设置得很大,因为一般情况下每一秒钟会将重做 日志缓冲刷新到日志文件,因此用户只需要保证每秒产生的事务量在这 个缓冲大小之内即可。该值可由配置参数innodb_log_buffer_size控制, 默认为8MB。

8MB的重做日志缓冲池足以满足绝大部分的应用,因为 重做日志在下列三种情况下会将重做日志缓冲中的内容刷新到外部磁盘的重做日志文件中。
a、Master Thread每一秒将重做日志缓冲刷新到重做日志文件;
b、每个事务提交时会将重做日志缓冲刷新到重做日志文件;
c、当重做日志缓冲池剩余空间小于1/2时,重做日志缓冲刷新到重做日 志文件。

1.4 额外的内存池

在InnoDB存储引擎中,对内存的管理是通 过一种称为内存堆(heap)的方式进行的。在对一些数据结构本身的内 存进行分配时,需要从额外的内存池中进行申请,当该区域的内存不够 时,会从缓冲池中进行申请。例如,分配了缓冲池 (innodb_buffer_pool),但是每个缓冲池中的帧缓冲(frame buffer)还 有对应的缓冲控制对象(buffer control block),这些对象记录了一些诸 如LRU、锁、等待等信息,而这个对象的内存需要从额外内存池中申 请。因此,在申请了很大的InnoDB缓冲池时,也应考虑相应地增加这 个值。

1.3 Checkpoint 技术

前面已经讲到了,缓冲池的设计目的为了协调CPU速度与磁盘速度的鸿 沟。因此页的操作首先都是在缓冲池中完成的。如果一条DML语句, 如Update或Delete改变了页中的记录,那么此时页是脏的,即缓冲池中 的页的版本要比磁盘的新。数据库需要将新版本的页从缓冲池刷新到磁 盘
倘若每次一个页发生变化,就将新页的版本刷新到磁盘,那么这个开销 是非常大的(修改频类很快,导致刷盘速度快,有可能发送刷盘速度小于内存修改速度)。若热点数据集中在某几个页中,那么数据库的性能将变得 非常差(如果只有几页修改,最好是等它修改了一段时间之后,统一刷盘。这样就减少了刷盘io)。同时,如果在从缓冲池将页的新版本刷新到磁盘时发生了宕 机,那么数据就不能恢复了。为了避免发生数据丢失的问题,当前事务 数据库系统普遍都采用了Write Ahead Log策略,即当事务提交时先写 重做日志再修改页。当由于发生宕机而导致数据丢失时,通过重做日 志来完成数据的恢复。这也是事务ACID中D(Durability持久性)的要 求。

因此Checkpoint(检查点)技术的目的是解决以下几个问题:

  • 缩短数据库的恢复时间(如果没有checkpoint,数据库的重做日志会持续增长,当发生宕机后,那么大的redo log 数据库所需要的恢复时间就很长。如果加了checkpoint之后,当数据库宕机之后,只需要恢复倒数第一次checkpoint之后的日志,大大减少了恢复时间);

  • 缓冲池不够用时,将脏页刷新到磁盘;

  • 重做日志不可用时,刷新脏页。

当缓冲池的内存不够用时,根据LRU算法会溢出最近最少使用的页,如果该页是脏页,那么会强制执行checkpoint,将该页刷盘。

重做日志出现不可用的情况是因为当前事务数据库系统对重做日志的设 计都是循环使用的,并不是让其无限增大的,这从成本及管理上都是比 较困难的。重做日志可以被重用的部分是指这些重做日志已经不再需 要,即当数据库发生宕机时,数据库恢复操作不需要这部分的重做日 志,因此这部分就可以被覆盖重用。若此时重做日志还需要使用,那么 必须强制产生Checkpoint,将缓冲池中的页至少刷新到当前重做日志的 位置。

对于InnoDB存储引擎而言,其是通过LSN(Log Sequence Number)来 标记版本的。而LSN是8字节的数字,其单位是字节。每个页有LSN, 重做日志中也有LSN,Checkpoint也有LSN。

在InnoDB存储引擎中,Checkpoint发生的时间、条件及脏页的选择等都 非常复杂。而Checkpoint所做的事情无外乎是将缓冲池中的脏页刷回到 磁盘。不同之处在于每次刷新多少页到磁盘每次从哪里取脏页,以及 什么时间触发Checkpoint。在InnoDB存储引擎内部,有两种 Checkpoint,分别为:

  • Sharp Checkpoint

  • Fuzzy Checkpoint

Sharp Checkpoint发生在数据库关闭时将所有的脏页都刷新回磁盘,这是 默认的工作方式,即参数innodb_fast_shutdown=1。

但是若数据库在运行时也使用Sharp Checkpoint,那么数据库的可用性就 会受到很大的影响。故在InnoDB存储引擎内部使用Fuzzy Checkpoint进 行页的刷新,即只刷新一部分脏页,而不是刷新所有的脏页回磁盘。那么Fuzzy Checkpoint 发生再什么情况?

  • Master Thread Checkpoint (差不多以每秒或每十秒的速度从缓冲池的脏页列 表中刷新一定比例的页回磁盘。这个过程是异步的,即此时InnoDB存 储引擎可以进行其他的操作,用户查询线程不会阻塞。)

  • FLUSH_LRU_LIST Checkpoint (也就是再清理LUR列表的时候发现了脏页,强制刷盘。是InnoDB1.2.x版本开始,这个检查被放在了 一个单独的Page Cleaner线程中进行,并且用户可以通过参数 innodb_lru_scan_depth控制LRU列表中可用页的数量,该值默认为 1024)

  • Async/Sync Flush Checkpoint

  • Dirty Page too much Checkpoint (脏页的数量太多, 导致InnoDB存储引擎强制进行Checkpoint。其目的总的来说还是为了保 证缓冲池中有足够可用的页。)

二、关键特性

1.1 插入缓冲

1 Insert Buffer

InnoDB缓冲池中有Insert Buffer信息固然不错,但是 Insert Buffer和数据页一样,也是物理页的一个组成部分

如果主键是递增的,那么再插入时磁盘是顺序读写,如果主键不是递增的那么磁盘就变成了随机读写,影响了磁盘速度。

InnoDB存储引擎开创性地设计了Insert Buffer,对于非聚集索引插入更新操作,不是每一次直接插入到索引页中,而是先判断插入的非聚 集索引页是否在缓冲池中,若在,则直接插入;若不在,则先放入到一 个Insert Buffer对象中,好似欺骗。数据库这个非聚集的索引已经插到叶 子节点,而实际并没有,只是存放在另一个位置。然后再以一定的频率 和情况进行Insert Buffer和辅助索引页子节点的merge(合并)操作,这 时通常能将多个插入合并到一个操作中(因为在一个索引页中),这就 大大提高了对于非聚集索引插入的性能。

然而Insert Buffer的使用需要同时满足以下两个条件:

  • 索引是辅助索引(secondary index);

  • 索引不是唯一(unique)的。

当满足以上两个条件时,InnoDB存储引擎会使用Insert Buffer,这样就 能提高插入操作的性能了。不过考虑这样一种情况:应用程序进行大量 的插入操作,这些都涉及了不唯一的非聚集索引,也就是使用了Insert Buffer。若此时MySQL数据库发生了宕机,这时势必有大量的Insert Buffer并没有合并到实际的非聚集索引中去。因此这时恢复可能需要很 长的时间,在极端情况下甚至需要几个小时。
辅助索引不能是唯一的,因为在插入缓冲时,数据库并不去查找索引页 来判断插入的记录的唯一性。如果去查找肯定又会有离散读取的情况发 生,从而导致Insert Buffer失去了意义。 (通俗的将就是辅助索引的页之前能被fix到内存,如果唯一的话,新增的页可能不会出现再内存)

2. Change Buffer

InnoDB从1.0.x版本开始引入了Change Buffer,可将其视为Insert Buffer 的升级。从这个版本开始,InnoDB存储引擎可以对DML操作—— INSERT、DELETE、UPDATE都进行缓冲,他们分别是:Insert Buffer、Delete Buffer、Purge buffer。

当然和之前Insert Buffer一样,Change Buffer适用的对象依然是非唯一的 辅助索引。
对一条记录进行UPDATE操作可能分为两个过程:

  • 将记录标记为已删除;
  • 真正将记录删除。

因此Delete Buffer对应UPDATE操作的第一个过程,即将记录标记为删 除。Purge Buffer对应UPDATE操作的第二个过程,即将记录真正的删 除。同时,InnoDB存储引擎提供了参数innodb_change_buffering,用来 开启各种Buffer的选项。该参数可选的值为:inserts、deletes、purges、 changes、all、none。inserts、deletes、purges就是前面讨论过的三种情 况。changes表示启用inserts和deletes,all表示启用所有,none表示都不 启用。该参数默认值为all。

3、Insert Buffer的内部实现

Insert Buffer的数据结构是一棵 B+树。在MySQL 4.1之前的版本中每张表有一棵Insert Buffer B+树。而 在现在的版本中,全局只有一棵Insert Buffer B+树,负责对所有的表的 辅助索引进行Insert Buffer。而这棵B+树存放在共享表空间中,默认也 就是ibdata1中。因此,试图通过独立表空间ibd文件恢复表中数据时, 往往会导致CHECK TABLE失败。这是因为表的辅助索引中的数据可能 还在Insert Buffer中,也就是共享表空间中,所以通过ibd文件进行恢复 后,还需要进行REPAIR TABLE操作来重建表上所有的辅助索引。

Insert Buffer是一棵B+树,因此其也由叶节点和非叶节点组成。非叶节 点存放的是查询的search key(键值),其构造如下图所示。

在这里插入图片描述

search key一共占用9个字节,其中space表示待插入记录所在表的表空间 id,在InnoDB存储引擎中,每个表有一个唯一的space id,可以通过 space id查询得知是哪张表。space占用4字节。marker占用1字节,它是 用来兼容老版本的Insert Buffer。offset表示页所在的偏移量,占用4字 节。
当一个辅助索引要插入到页(space,offset)时,如果这个页不在缓冲 池中,那么InnoDB存储引擎首先根据上述规则构造一个search key,接 下来查询Insert Buffer这棵B+树,然后再将这条记录插入到Insert Buffer B+树的叶子节点中。

下图展示了Insert Buffer B+树叶子节点的记录,并不是直接将待插入的记录插入,而是需要根据如下的规则进行构造:

在这里插入图片描述

space、marker、offset字段和之前非叶节点中的含义相同,一共占用9 字节。第4个字段metadata占用4字节,其存储的内容如表2-2所示。

在这里插入图片描述

IBUF_REC_OFFSET_COUNT是保存两个字节的整数,用来排序每个记 录进入Insert Buffer的顺序。因为从InnoDB1.0.x开始支持Change Buffer,所以这个值同样记录进入Insert Buffer的顺序。通过这个顺序回 放(replay)才能得到记录的正确值(也就是说可以insert和update同样的值,那么如果没有顺序的话不知道最终得结果)。
从Insert Buffer叶子节点的第5列开始,就是实际插入记录的各个字段 了。因此较之原插入记录,Insert Buffer B+树的叶子节点记录需要额外 13字节(9个字节的space+marker+offset和4个字节的meate字段前4位)的开销。

因为启用Insert Buffer索引后,辅助索引页(space,page_no)中的记录 可能被插入到Insert Buffer B+树中,所以为了保证每次Merge Insert Buffer页必须成功,还需要有一个特殊的页用来标记每个辅助索引页 (space,page_no)的可用空间。这个页的类型为Insert Buffer Bitmap(它记录了每一个辅助索引页可用空间得数量)。

怎么保证Merge Insert Buffer成功?
因为insert buffer bitmap中记录了每一个辅助索引页得剩余空间,所以当辅助索引页得空间剩余很小得时候,要进行一次merge操作,这样就可以保证merge成功
4、Merge Insert Buffer

通过前面的小节读者应该已经知道了Insert/Change Buffer是一棵B+树。 若需要实现插入记录的辅助索引页不在缓冲池中,那么需要将辅助索引 记录首先插入到这棵B+树中。但是Insert Buffer中的记录何时合并 (merge)到真正的辅助索引中呢?这是本小节需要关注的重点。

概括地说,Merge Insert Buffer的操作可能发生在以下几种情况下:

  • 辅助索引页被读取到缓冲池时;

  • Insert Buffer Bitmap页追踪到该辅助索引页已无可用空间时;

  • Master Thread。

第一种情况为当辅助索引页被读取到缓冲池中时,例如这在执行正常的 SELECT查询操作,这时需要检查Insert Buffer Bitmap页,然后确认该辅 助索引页是否有记录存放于Insert Buffer B+树中。若有,则将Insert Buffer B+树中该页的记录插入到该辅助索引页中。可以看到对该页多次 的记录操作通过一次操作合并到了原有的辅助索引页中,因此性能会有 大幅提高。

Insert Buffer Bitmap页用来追踪每个辅助索引页的可用空间,并至少有 1/32页的空间。若插入辅助索引记录时检测到插入记录后可用空间会小 于1/32页,则会强制进行一个合并操作,即强制读取辅助索引页,将 Insert Buffer B+树中该页的记录及待插入的记录插入到辅助索引页中。 这就是上述所说的第二种情况。

Master Thread线 程中每秒或每10秒会进行一次Merge Insert Buffer的操作,不同之处在于 每次进行merge操作的页的数量不同。

1.2 两次写(double write)

doublewrite(两次写)带给InnoDB存储引擎的是数据页的可靠性。

当发生数据库宕机时,可能InnoDB存储引擎正在写入某个页到表中, 而这个页只写了一部分,比如16KB的页(innoDB存储最小单位),只写了前4KB(磁盘最小存储单位),之后就发生 了宕机,这种情况被称为部分写失效(partial page write)。在InnoDB 存储引擎未使用doublewrite技术前,曾经出现过因为部分写失效而导致 数据丢失的情况。

有经验的DBA也许会想,如果发生写失效,可以通过重做日志进行恢 复。这是一个办法。但是必须清楚地认识到,重做日志中记录的是对页 的物理操作,如偏移量800,写’aaaa’记录。如果这个页本身已经发生了 损坏(理解为数据库物理页发生异常,也就说redo 日志得生效需要对应得物理页存在且可以正常操作),再对其进行重做是没有意义的。这就是说,在应用(apply)重 做日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副 本来还原该页,再进行重做,这就是doublewrite(整体可以理解为,需要一个机制来恢复被破坏得物理页)。

下图表示InnoDB存储引擎中 doublewrite的体系架构

在这里插入图片描述

doublewrite由两部分组成,一部分是内存中的doublewrite buffer,大小 为2MB,另一部分是物理磁盘上共享表空间中连续的128个页,即2个区 (extent),大小同样为2MB(128*16kb)。在对缓冲池的脏页进行刷新时,并不直 接写磁盘,而是会通过memcpy函数将脏页先复制到内存中的 doublewrite buffer,之后通过doublewrite buffer再分两次,每次1MB顺序 地写入共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘, 避免缓冲写带来的问题。在这个过程中,因为doublewrite页是连续的, 因此这个过程是顺序写的,开销并不是很大。在完成doublewrite页的写 入后,再将doublewrite buffer中的页写入各个表空间文件中,此时的写 入则是离散的。

如果操作系统在将页写入磁盘的过程中发生了崩溃,在恢复过程中, InnoDB存储引擎可以从共享表空间中的doublewrite中找到该页的一个副 本,将其复制到表空间文件,再应用重做日志。

1.3 自适应哈希索引

哈希(hash)是一种非常快的查找方法,在一般情况下这种查找的时间 复杂度为O(1),即一般仅需要一次查找就能定位数据。而B+树的查找次 数,取决于B+树的高度,在生产环境中,B+树的高度一般为3~4层, 故需要3~4次的查询

InnoDB存储引擎会监控对表上各索引页的查询。如果观察到建立哈希 索引可以带来速度提升,则建立哈希索引,称之为自适应哈希索引 (Adaptive Hash Index,AHI)。

AHI是通过缓冲池的B+树页构造而 来,因此建立的速度很快,而且不需要对整张表构建哈希索引。

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

AHI有一个要求,即对这个页的连续访问模式必须是一样的。例如对于 (a,b)这样的联合索引页,其访问模式可以是以下情况:

  • WHERE a=xxx

  • WHERE a=xxx and b=xxx

访问模式一样指的是查询的条件一样,若交替进行上述两种查询,那么 InonDB存储引擎不会对该页构造AHI。此外AHI还有如下的要求:

  • 以该模式访问了100次

  • 页通过该模式访问了N次,其中N=页中记录*1/16

值得注意的是,哈希索引只能用来搜索等值的查 询,如SELECT*FROM table WHERE index_col=‘xxx’。而对于其他查找 类型,如范围查找,是不能使用哈希索引的。

1.4 异步IO

为了提高磁盘操作性能,当前的数据库系统都采用异步 IO(Asynchronous IO,AIO)的方式来处理磁盘操作。InnoDB存储引擎 亦是如此。
与AIO对应的是Sync IO,即每进行一次IO操作,需要等待此次操作结束 才能继续接下来的操作。但是如果用户发出的是一条索引扫描的查询, 那么这条SQL查询语句可能需要扫描多个索引页,也就是需要进行多次 的IO操作。在每扫描一个页并等待其完成后再进行下一次的扫描,这是 没有必要的。用户可以在发出一个IO请求后立即再发出另一个IO请求, 当全部IO请求发送完毕后,等待所有IO操作的完成,这就是AIO。 AIO的另一个优势是可以进行IO Merge操作,也就是将多个IO合并为1 个IO,这样可以提高IOPS的性能。例如用户需要访问页的(space, page_no)为: (8,6)、(8,7),(8,8) 每个页的大小为16KB,那么同步IO需要进行3次IO操作。而AIO会判断 到这三个页是连续的(显然可以通过(space,page_no)得知)。因此 AIO底层会发送一个IO请求,从(8,6)开始,读取48KB的页。

这里up觉得,这里得异步IO对应得应该是我们所熟知得同步非阻塞io,而不是所谓真正得异步io.

1.5 刷新邻接页

InnoDB存储引擎还提供了Flush Neighbor Page(刷新邻接页)的特性。 其工作原理为:当刷新一个脏页时,InnoDB存储引擎会检测该页所在 区(extent)的所有页,如果是脏页,那么一起进行刷新。这样做的好 处显而易见,通过AIO可以将多个IO写入操作合并为一个IO操作,故该 工作机制在传统机械磁盘下有着显著的优势。但是需要考虑到下面两个 问题:

是不是可能将不怎么脏的页进行了写入,而该页之后又会很快变成脏 页?

固态硬盘有着较高的IOPS,是否还需要这个特性? 为此,InnoDB存储引擎从1.2.x版本开始提供了参数 innodb_flush_neighbors,用来控制是否启用该特性。对于传统机械硬盘 建议启用该特性,而对于固态硬盘有着超高IOPS性能的磁盘,则建议将 该参数设置为0,即关闭此特性。

,那么一起进行刷新。这样做的好 处显而易见,通过AIO可以将多个IO写入操作合并为一个IO操作,故该 工作机制在传统机械磁盘下有着显著的优势。但是需要考虑到下面两个 问题:

是不是可能将不怎么脏的页进行了写入,而该页之后又会很快变成脏 页?

固态硬盘有着较高的IOPS,是否还需要这个特性? 为此,InnoDB存储引擎从1.2.x版本开始提供了参数 innodb_flush_neighbors,用来控制是否启用该特性。对于传统机械硬盘 建议启用该特性,而对于固态硬盘有着超高IOPS性能的磁盘,则建议将 该参数设置为0,即关闭此特性。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《MySQL 技术内幕 InnoDB 存储引擎》是一本探讨 MySQLInnoDB 存储引擎的技术书籍,该书主要讲解了 InnoDB 存储引擎的原理、架构和实现细节。 InnoDBMySQL 数据库的默认存储引擎,具有事务处理和行级锁定等特性,广泛应用于企业级数据库系统。因此,了解 InnoDB 存储引擎的内部工作原理和性能优化技巧对于 MySQL 数据库的使用和优化非常重要。 这本书首先介绍了数据库系统和存储引擎的基本概念,然后详细讲解了 InnoDB 存储引擎的体系结构和核心组件。读者可以了解到 InnoDB 存储引擎是如何将数据存储在磁盘上,以及如何通过索引加快查询速度。 在介绍完基础知识之后,书中继续深入讲解了 InnoDB 存储引擎的事务处理机制、并发控制和崩溃恢复等关键技术。读者可以学习到如何正确使用事务,并了解到 InnoDB 是如何通过行级锁定来实现并发访问的。 此外,书中还涵盖了 InnoDB 存储引擎的性能优化技巧和调试方法。读者可以学习到如何通过合理的配置和索引设计来提升查询性能,以及如何通过监控和分析工具来定位和解决性能问题。 总之,《MySQL 技术内幕 InnoDB 存储引擎》是一本深入剖析 InnoDB 存储引擎的权威技术书籍,对于想要深入理解和优化 MySQL 数据库的开发人员和数据库管理员来说是一本非常有价值的参考资料。 ### 回答2: 《MySQL技术内幕InnoDB存储引擎》是一本深入讲解MySQL InnoDB存储引擎的技术书籍。InnoDBMySQL中的一种存储引擎,相比其他存储引擎,如MyISAM,它拥有更好的事务支持和并发控制能力,可以提供更高的数据一致性和可靠性。 这本书主要从架构、存储、索引、事务、锁定等方面对InnoDB存储引擎进行了详细的介绍和分析。首先,作者介绍了InnoDB的整体架构,包括缓冲池、日志系统、刷新机制等,帮助读者理解InnoDB的内部工作原理。 然后,书中详细解释了InnoDB的物理存储机制,包括页结构、数据页、索引页等。通过了解这些概念,读者可以更好地理解数据在磁盘上的存储方式,进而优化查询性能和空间利用。 接着,书中介绍了InnoDB的索引机制,包括B+树索引和自适应哈希索引。通过学习这些索引类型的原理和使用方法,读者可以更好地选择和创建适合自己业务需求的索引,提高查询效率。 此外,该书还详细说明了InnoDB的事务处理机制,包括事务的隔离级别、锁定机制、行锁和表锁等。通过学习这些内容,读者可以更好地理解和掌握InnoDB的并发控制技术,避免数据冲突和锁定问题。 总而言之,《MySQL技术内幕InnoDB存储引擎》通过深入讲解InnoDB的各个方面,帮助读者更好地理解和应用该存储引擎。无论是MySQL开发人员还是DBA,都可以从这本书中获得对InnoDB的深入了解,提高数据库性能和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值