--InnoDB storage engine InnoDB storage engine


MySQL is InnoDB transaction-safe storage engine, uses a similar architecture with Oracle database design. In general, InnoDB storage engine is the core OLTP applications in the table storage engine of choice.

1. InnoDB Storage Engine Overview

The storage engine is the first full support for ACID transactions MySQL storage engine, which features a row lock designed to support MVCC, support for foreign keys, locks provide a consistent set of non-reading, and was designed to most effectively utilize and use memory and the CPU.

2. InnoDB storage engine version

  1. Old versions of InnoDB: support for ACID, line lock, MVCC
  2. InnoDB 1.0.x: increased compress and dynamic page format
  3. InnoDB 1.1.x: increased Linux AIO, and more rollback
  4. InnoDB 1.2.x: adds support for full-text indexing, online index added

3. InnoDB architecture

A plurality of internal engines InnoDB storage memory blocks, memory blocks may be considered to constitute such a large pool of memory

Here Insert Picture Description

Background thread: The main role is to refresh the memory pool of data, to ensure that the buffer pool cache memory is the most recent data, in addition to refresh the modified data to a disk file, while ensuring that when an abnormality occurs InnoDB database can be restored to normal with operating condition.

(1). Background thread

InnoDB storage engine is a model of multi-threaded, so the background there are a number of different background thread responsible for handling different tasks.

1). Master Thread

The main buffer pool asynchronous data flushed to disk to ensure data consistency.

2). IO Thread

InnoDB storage engine to handle the extensive use of AIO write IO requests, which can greatly improve the performance of the database, and IO Thread work as long as the callback handler responsible for these IO requests.

3). Purge Thread

Recycling has been used and allocated undo page.

(Undo: before the operation data, will now back up data to a place and then modify, the backup called undo log)

4). Page Cleaner Thread

Refresh dirty pages are put into a separate thread to complete.

(2) Memory

1). Pool

InnoDB storage engine is a disk-based storage, and which records are managed in a manner page so they can be treated as. Disk-based database systems typically use buffer pool technology to improve the overall performance of disk-based database system database

Pool is simply a memory area by the memory speed to compensate for the slower disk speed impact on database performance. Follow read page in the database, the first page read from the disk on the pool in. the next time when reading the same page, first determine whether the page in the buffer pool, if, say the page is in the buffer pool hit directly read the page, otherwise, read the page on disk.

Modification operations on the database page, the first page in the buffer pool modify, and then at a certain frequency flushed to disk. Refresh back to the disk through the mechanism of Checkpoint

Buffer pool size directly affects the overall performance of the database.

Buffer pool configuration parameters set by innodb_buffer_pool_size

Specifically, the cache buffer pool page types: index page, data pages, pages Use the undo, insert buffer, adaptive hash index, InnoDB lock information stored in the data dictionary and the like.

Here Insert Picture Description
 From InnoDB1.0.x version, it allows multiple instances pool. Each page assigned to a different average buffer pool instances based on a hash value, the buffer pool can be configured by the example parameters innodb_buffer_pool_instances, defaults to 1

It can be observed state of each instance of an object pool run through the command SHOW ENGINE INNODB STATUS

2). LRU list,Free list和Flush list

Generally, the database buffer pool by LRU (Latest Recent Used, Least Recently Used) algorithm to manage. The most frequently used pages and the front end of the LRU list, the least used pages at the end of the LRU list when the buffer pool can not store a new page, release the end of the page.

The default size of the buffer pool page is 16K.

InnoDB storage engine is also conventional LRU algorithm is optimized by adding the midpoint position.

New page read, although the latest visit of the page, but not necessarily always active page, directly into the front end of the list there is something wrong .InnoDB optimize storage engine for the new page inserted to set a good midpoint position the default for the former at 5/8 .InnoDB storage engine will list the length of the table before the midpoint become new list, called the old list after page. (Another reason is that, if the scanning operation is carried out, then all page will enter the LRU list once to insert the front will refresh the entire LRU list)

InnoDB storage engine is also provided innodb_old_blocks_time parameters for the hot end of the page after how long it will set the read page into the LRU list.

Just start the database, LRU list is empty, all the pages are stored in the Free list. When you need to first find the page from the buffer pool allocations from the Free list for available free pages, if you have the free page Free deleted from the list, and inserted into the LRU list. otherwise, out of a page from the LRU end of the list, re-allocate memory.

​  LRU列表中的页被修改后,被称为脏页.而Flush列表中的页即为脏页.需要注意的是,脏页既存在于Flush列表中,页存在于LRU列表中.

​  可以通过 SHOW ENGINE INNOB STATUS 来观察LRU列表以及Free列表的使用情况和运行状态,具体可参考mysql之show engine innodb status解读或者参考MySQL技术内幕InnoDB存储引擎第二版P27

​  InnoDB从1.0x版本开始支持压缩页功能,即将原本16KB的页进行压缩。对于非16KB的页,通过unzip_LRU进行管理,其次通过伙伴算法进行内存的分配。例如对需要从缓冲池中申请页为4KB的大小,过程如下

  1. 检查4KB的unzip_LRU列表,检查是否有可用空闲页
  2. 若有,则直接使用
  3. 否则,检查8KB的unzip_LRU列表
  4. 如能够得到空闲页,将页分成2个4KB页,存放到4KB的unzip_LRU列表
  5. 若不能得到空闲页,从LRU列表中申请一个16KB的页,将页分为1个8KB的页和2个4KB的页,分别存放到对应的unzip_LRU列表

​  LRU列表用于管理缓冲池中页的可用性,Flush列表用来管理将页刷新会磁盘,二者互不影响.同理,Flush列表也可以通过命令SHOW ENGINE INNODB STATUS查看。

3). 重做日志缓冲

​  InnoDB存储引擎首先将重做日志先放入到这个缓冲区,然后按一定频率将其刷新到重做日志文件,这个缓冲一般不会设置的很大,因为一般情况下每一秒都会有刷新操作.由参数innodb_log_buffer_size控制,默认大小为8MB.

​ 有三种情况会将重做日志缓冲中的内容刷新到外部磁盘的重做日志中

  • Master Thread 每一秒将重做日志缓冲刷新到重做日志文件
  • 每个事务提交时会将重做日志缓冲刷新到重做日志文件
  • 当重做日志缓冲池剩余空间小于1/2时,重做日志缓冲刷新到重做日志文件

4). 额外的缓冲池

​  在InnoDB存储引擎中,堆内存的管理是通过一种成为内存堆的方式进行的,在对一些数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当该区域的内存不够时,会从缓冲池中进行申请.

4. Checkpoint技术

​  为了避免发生数据丢失的问题,当前的事务数据库系统普遍都采用了Write Ahead Log策略,即当事务提交时,先重写日志,再修改页.当由于发生宕机而导致数据丢失时,通过重做日志来完成数据恢复。

​  那么试想,是不是可以只保存日志,完全通过日志来恢复整个数据库系统中的数据带宕机发生的时刻,这需要两个前提条件:

  1. 缓冲池可以缓存数据库中所有数据
  2. 重做日志可以无线增大

​  如果上面两个条件都满足,还需要考虑宕机后数据恢复的时间.因此Checkpoint技术的目的主要是解决

  • 缩短数据的恢复时间
  • 缓冲池不够用时,刷新脏页
  • 重做日志不可用时,刷新脏页

​  所以,出现了Checkpoint技术,当数据库发生宕机时,不需要重做所有的日志,因为Checkpoint之前的页都已经刷新回磁盘了.当缓冲池不够用时,根据LRU算法会溢出最近最少使用的页,如果此页为脏页,会强制执行Checkpoint,将脏页刷新回磁盘.

​  对于InnoDB存储引擎而言,是通过LSN来标记版本的.而LSN是8字节的数据,其单位是字节.

在InnoDB存储引擎内部,有两种Checkpoint:

  • Sharp Checkpoint:刷新全部脏页
  • Fuzzy Checkpoint:在InnoDB内部使用,只刷新部分脏页

发生Fuzzy Checkpoint的几种情况:

  1. Master Thread Checkpoint:在Master Thread中定时发生的.
  2. FLUSH_LRU_LIST Checkpoint:为了保证LRU列表中有差不多100个空闲页,当移除尾端页时,会进行Checkpoint.
  3. Async/Sync Flush Checkpoint:重做日志不可用时,会将一些页强制刷新回磁盘.
  4. Dirty Page too much Checkpoint:脏页数量太多,会发生Checkpoint

5. Master Thread的工作方式

(1). InnoDB 1.0.x版本之前

​  内部由多个循环组成:主循环(loop),后台循环(backgroup loop),刷新循环(flush loop),暂停循环(suspend loop).Master Thread会根据数据库的状态在这些循环之间进行切换.

​  Loop被称为主循环,其中有两大操作-----每十秒的操作和每秒都进行的.

​  loop循环通过thread sleep实现,这意味这这些操作之间的计时是不准确的.

每一秒进行的操作:

  • 日志缓冲刷新到磁盘,即时还没有提交事务
  • 可能会合并插入缓冲(通过判断前一秒发生IO的次数判断IO压力是否小,从而决定是否进行合并插入缓冲)
  • 可能会刷新脏页到磁盘(脏页比例超过参数设置的值,会进行刷新,默认值为90%)
  • 如果当前没有用户活动,可能会切换到backgroup loop

每十秒进行的操作:

  • 可能会刷新100个脏页(判断过去十秒内IO次数是否小于200次)
  • 合并最多5个插入缓冲
  • 将日志缓冲刷新到磁盘
  • 删除无用的undo页
  • 刷新100或者10个脏页到磁盘

​ 如果当前没有用户活动或者数据库关闭,就会切换到background loop,在这个循环内,会执行以下操作:

  • 删除无用的Undo页
  • 合并20个插入循环
  • 跳回到主循环
  • 也可能会调到flush loop中不断刷新100个页直到符合条件

(2). InnoDB 1.2.x版本之前

​  在之前的版本中,由于硬编码,即时每秒内有很多的页写入和多个插入缓冲的合并,Master Thread只会选择刷新其中的100个脏页和20个插入缓冲,当发生宕机时,会积累很多的数据没有刷新回磁盘,导致恢复的时间会需要很久.

​  从InnoDB 1.0.x版本开始,提供了innodb_io_capacity参数来表示磁盘IO吞吐量,默认为200.对于刷新到磁盘的数量,会按照该参数的百分比进行控制:

  • 合并插入缓冲时,每次合并数量为该参数的5%.
  • 刷新脏页时,刷新的数量为该参数的值.

​  从InnoDB 1.0.x版本开始,刷新脏页时的脏页占比参数innodb_max_dirty_pages_pct默认值由90变为了75.加快了脏页的刷新频率.

​  引入了参数来判断需要刷新脏页的最适合的数量,其内部方法通过判断重做日志的速度来判断最适合的刷新脏页数量.

​  引入了控制每次full purge()回收Undo页的数量的参数,默认为20.

​  InnoDB还对主循环内部进行了优化,使压力大时不一定总是等待1秒.

(3). InnoDB1.2.x版本

​  对于脏页的刷新操作,从Master Thread线程分离到一个单独的Page Cleaner Thread进行.

6. InnoDB关键特性

  • 插入缓冲
  • 两次写
  • 自适应哈希索引
  • 异步IO
  • 刷新邻接页

(1). 插入缓冲

1). Insert Buffer

​  Insert Buffer和数据也一样,也是物理页的一部分,并不是缓冲池的组成.

​  在InnoDB存储引擎中,主键是行唯一的标识符,通常应用程序中行记录的插入都是按照主键递增的顺序插入的.

​  但是对于非聚集索引,插入的顺序是离散的.(聚集索引是指数据航的物理顺序与列值的逻辑顺序顺序相同,一张表中只能有一个索引)

​  InnoDB存储引擎开创性的设计了Insert Buffer,对于非聚集索引的插入或更新操作,不是每一次的直接插入到索引页中,而是先判断插入的非聚集索引是否在缓冲池中,如果在直接插入(这样是直接操作内存的,很快),如果不在,先放入一个Insert Buffer对象中.然后在以一定的频率将多个插入合并到一个操作中.

Insert Buffer的使用必须满足一下两个条件:

  1. 索引是辅助索引:叶子节点中存储主键值,每次查找时,现根据索引找到叶子节点中的主键值,才从聚集索引中得到完整记录.
  2. 索引不是唯一的:如果唯一,每一次插入会先查找判重复,违背了Insert Buffer减少操作索引次数的目的.

​  但是,Insert Buffer存在一个问题,在写密集的情况下,插入缓冲会占用过多的缓冲池内存(虽然保存在物理磁盘,但是缓冲池中还是有这部分信息的)

2). Change Buffer

​  从InnoDB 1.0.x版本开始引入了Change Buffer,可将其视为Insert Buffer的升级.从这个版本开始,可以对DML操作–insert,delete,update都进行缓冲.

3). Insert Buffer的内部实现

​  Insert Buffer的数据结构是一颗B+树,非叶节点存放的是查询的search key(键值).

search key占9字节:

  • space:4字节,表示待插入记录所在表的表空间id.
  • marker:1字节,用来兼容老版本的Insert Buffer.
  • offset:4字节,表示页所在的偏移量.

叶节点存储的数据结构如下:

  • 前三个字段和search key一样,共占9字节.
  • metadata:4字节,又分为以下三个部分:
    • IBUF_REC_OFFSET_COUNT:2字节,表示进入Insert Buffer的顺序.
    • IBUF_REC_OFFSET_TYPE:1字节
    • IBUF_REC_OFFSET_FLAGS:1字节
  • secondary index record:实际插入的值.

​  为了保证每次合并插入缓冲都必须成功,必须要有一个特殊的页来标记每个辅助索引页的可用空间,类型为Insert Buffer Bitmap.

​  每个Insert Buffer Bitmap页用来追踪16384个辅助索引页,也就是256个区.每一个Insert Buffer Bitmap都会紧跟在这16384个页后面.

4). Merge Insert Buffer

Merge Insert Buffer(合并)操作发生在以下几种情况下:

  • 辅助索引被读取到缓冲池
  • Insert Buffer Bitmap页追踪到该辅助索引页没有可用空间(剩余空间不足1/32页)
  • Master Thread(主循环定时合并),每次只合并一部分页,由InnoDB存储引擎在Insert Buffer B+树中随机读取

(2). 两次写

​  如果在InnoDB存储引擎写入一个页的过程中,发生了宕机,此时这个页被写了一半,已经与前一次Checkpoint后的磁盘不一致了,使用重做日志是无法恢复的.

​  doublewrite由两部分组成,一部分是内存中的doublewrite buffer,大小为2MB,另一部分是物理磁盘上共享表空间中的128个页(两个区),大小也为2MB.

​  在对脏页进行刷新时,会先将脏页先复制到内存中的doublewrite buffer,然后同步磁盘,这个操作非常快.完成之后在将doublewrite buffer中的页写入到各个表空间中.相当于在本地磁盘中先快速写入一遍,作为副本,这个副本和本地磁盘中的数据总有一个是干净的

Here Insert Picture Description

(3). 自适应哈希索引

​  InnoDB存储引擎会监控对表上个索引的查询.如果观察到建立哈希索引可以带来速度提升,则建立哈希索引(Adaptive Hash Index,AHI).AHI是通过缓冲池的B+树构造而来,因此建立的速度很快,而且不需要对整张表构建哈希索引. InnoDB存储引擎会自动根据访问的频率和模式来自动地为某些热点页建立哈希索引.

​  有一个要求就是对这个页的连续访问必须使用相同的查询条件.

​  哈希索引只能用来搜索等值的查询.对于范围查找,是不能使用哈希索引的.

(4). 异步IO

​  为了提高磁盘操作性能,当前的数据库系统都采用异步IO(AIO)的方式来处理磁盘操作.与之相对应的是Sync IO,即没进行一次IO操作,需要等待此次操作结束才嫩而过继续接下来的操作.

​  异步IO就是指用户可以在发出一个IO请求后立即在发出另一个IO请求,全部的IO请求发出后,等待所有的IO操作完成,这就是AIO.

​  另一个优势,是可以进行IO Merge操作,也就是将多个IO合并为一个IO请求,从而提高IOPS性能.

(5). 刷新邻接页

​  当刷新一个脏页时,InnoDB存储引擎会尖刺该页所在的区的所有页,如果是脏页,那么一起进行刷新.

​  对于固态硬盘,建议关闭此特性.

7. 启动,关闭与修复

​  关闭数据库时,参数innodb_fast_shutdown影响着存储引擎为InnoDB的表的行为.

innodb_fast_shutdown参数含义:

  • 0:MySQL关闭时,InnoDB需要完成所有的无用Undo页清除和合并插入缓存,并且刷新所有脏页会磁盘.
  • 1:只刷新脏页.
  • 2:将日志写入日志文件,下次MySQL数据库启动时进行恢复.

​  参数innodb_force_recovery影响了整个InnoDB存储引擎恢复的状况.该参数默认为0,表示当需要恢复时,进行所有的恢复操作,当不能进行有效恢复(比如发生了数据库坏块),MySQL数据库可能发生宕机,并将错误记录到错误日志中.还有6个可以设置的值来屏蔽一些错误.

  • 1(SRV_FORCE_IGNORE_CORRUPT):忽略检查到的corrupt页
  • 2(SRV_FORCE_NO_BACKGROUND):阻止主线程的运行,如主线程需要执行full purge操作,会导致crash
  • 3(SRV_FORCE_NO_TRX_UNDO):不执行事务回滚操作
  • 4(SRV_FORCE_NO_IBUF_MERGE):不执行插入缓冲的合并操作
  • 5(SRV_FORCE_NO_UNDO_LOG_SCAN):不查看撤销日志(Undo Log),InnoDB存储引擎会将未提交的事务视为已提交
  • 6(SRV_FORCE_NO_LOG_REDO):不执行前滚的操作

​  当innodb_force_recovery参数不为0时,insert,update和delete这类DML操作都是不允许的.

发布了141 篇原创文章 · 获赞 47 · 访问量 4万+

Guess you like

Origin blog.csdn.net/qq_41596568/article/details/104332210