--InnoDBストレージエンジンInnoDBストレージエンジン


MySQLは、InnoDBのトランザクションセーフストレージエンジンであるOracleデータベースの設計と同様のアーキテクチャを使用しています。一般的には、InnoDBストレージエンジンは、選択したテーブルのストレージエンジンの中核OLTPアプリケーションです。

1. InnoDBストレージエンジンの概要

ストレージエンジンは、ロックは、非読み出しの一貫したセットを提供し、MVCC、外部キーのサポートをサポートするように設計された行ロックを特徴ACIDトランザクションのMySQLストレージエンジン、のための最初のフルサポート、最も効果的に利用し、使用するように設計しました。メモリとCPU。

2.はInnoDBストレージエンジンのバージョン

  1. InnoDBの旧バージョン:ACID、ラインロック、MVCCのためのサポート
  2. InnoDBは1.0.xの:増加湿布と動的ページのフォーマット
  3. InnoDBのバージョン1.1.x:LinuxのAIOを増加し、より多くのロールバック
  4. InnoDBは1.2.xの:オンラインインデックスを追加し、フルテキストインデックスのサポートを追加

3. InnoDBのアーキテクチャ

内部エンジンのInnoDB記憶複数のメモリブロック、メモリブロックは、メモリのような大規模なプールを構成すると考えることができます

ここに画像を挿入説明

バックグラウンドスレッド:主な役割は、異常が発生した場合のInnoDBデータベースで正常に戻すことができることを確保しつつ、ディスクファイルに変更されたデータをリフレッシュするだけで、データのメモリ・プールをリフレッシュするためにバッファプールキャッシュメモリが最新のデータであることを保証することです運転状態。

(1)バックグラウンドスレッド

InnoDBストレージエンジンが異なるタスクの処理を担当異なるバックグラウンドスレッドの数があるマルチスレッドのモデルなので、バックグラウンドです。

1)。マスタースレッド

メインバッファ・プール非同期データは、データの一貫性を確保するために、ディスクにフラッシュ。

2)。IOスレッド

InnoDBストレージエンジンが大幅に長いこれらのIO要求を担当するコールバックハンドラのようにデータベースのパフォーマンス、およびIOスレッドの仕事を向上させることができAIO書き込みIO要求を多用し、処理します。

3)。パージスレッド

リサイクルを使用して元に戻すページを割り当てられています。

(元に戻すには:運転データの前に、今、変更後、アンドゥログと呼ばれるバックアップを場所にデータをバックアップします)

4)。ページクリーナースレッド

リフレッシュ汚れたページを完了するために、別のスレッドに入れています。

(2)メモリ

1)。プール

InnoDBストレージエンジンは、ディスクベースのストレージである、と彼らは次のように扱うことができるので、そのレコードは仕方のページで管理されています。ディスクベースのデータベース・システムは、通常、ディスク・ベースのデータベース・システムのデータベースの全体的なパフォーマンスを改善するために、バッファプールの技術を使用します

プールは、データベースのパフォーマンスに、より遅いディスク速度の影響を補正するために、単純にメモリ速度によるメモリ領域です。フォローは、データベース内のページを読んで、最初のページには、プール上のディスクから読み取ります同じページを読み込む次回。で、第1のバッファプール内のページかどうかを判断すると、ページがバッファプール内にあると言う、場合は、ディスク上のページを読んで、それ以外の場合は、直接ページを読んで打ちます。

データベース・ページの変更操作は、バッファプール内の最初のページが変更し、特定の周波数でディスクにフラッシュ。チェックポイントの機構を介してディスクに更新バック

バッファー・プール・サイズは、直接データベースの全体的なパフォーマンスに影響を与えます。

innodb_buffer_pool_sizeによって設定されたバッファプールの設定パラメータ

具体的には、キャッシュ・バッファプールのページ・タイプ:インデックス・ページ、データページ、ページがデータ・ディクショナリなどに保存されているアンドゥ、挿入バッファ、適応ハッシュインデックス、InnoDBのロック情報を使用してください。

ここに画像を挿入説明
 InnoDB1.0.xのバージョンから、それは複数のインスタンスのプールを可能にする。ハッシュ値に基づいて、異なる平均バッファー・プール・インスタンスに割り当てられた各ページを、バッファ・プールを1に、例えばパラメータinnodb_buffer_pool_instancesによってデフォルト値を設定することができ

これは、コマンドSHOWエンジンINNODBステータスを通じてオブジェクト・プール・ランの各インスタンスの観察状態とすることができます

2)。LRUリスト、フリーリスト和フラッシュ一覧

一般的に、LRUにより、データベース・バッファ・プール(最新の最近の使用済み、最低使用頻度)アルゴリズムが管理しています。最も頻繁に使用されるページやLRUリストのフロントエンドを、LRUリストの最後に少なくとも使用されるページバッファー・プールは、新しいページを保存することができない場合は、ページの最後をリリース。

バッファー・プール・ページのデフォルトのサイズは16Kです。

InnoDBストレージエンジンは、従来のLRUアルゴリズムが中点位置を追加することによって最適化されます。

新しいページが良い中点位置を設定するために挿入された新しいページのために何かを間違っ.InnoDB最適化ストレージエンジンがあり、直接リストの前端部に、ページをページの最新の訪問が、読んで、必ずしも必要ではないが、常にアクティブ5/8 .InnoDBストレージエンジンの元のデフォルトの中間点は、ページの後に、古いリストと呼ばれる新しいリスト、なる前に、テーブルの長さが一覧表示されます。(もう一つの理由は、スキャン操作はすべて、実行された場合に、ということです全体のLRUリストを更新しますフロントを挿入した後のページ)はLRUリストに入ります

InnoDBストレージエンジンはまた、LRUリストに読み出したページを設定する期間の後にページのホットエンドのためinnodb_old_blocks_timeパラメータを提供します。

ただ、データベースを起動し、LRUリストが空である、すべてのページがフリーリストに格納されている。あなたが最初に使用可能な空きページのためのフリーリストからバッファプール割り当てからページを見つける必要がある場合は、あなたが自由にページを持っている場合フリーはリストから削除され、LRUリストに挿入された。それ以外の場合は、リストのLRU端からページのうち、再割り当てメモリ。

​  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中的页写入到各个表空间中.相当于在本地磁盘中先快速写入一遍,作为副本,这个副本和本地磁盘中的数据总有一个是干净的

ここに画像を挿入説明

(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万+

おすすめ

転載: blog.csdn.net/qq_41596568/article/details/104332210