MySQL技术内幕-InnoDB存储引擎

第一章 MySQL体系结构和存储引擎

数据库和数据库实例:

  • 数据库是文件的集合,是依照某种数据模型组织起来存放于二进制存储器中的数据集合。
  • 数据库实例是程序,是位于用户与操作系统之间的一层数据管理软件,用户对数据库的任何操作,包括数据库定义、查询、数据维护、数据库运行控制等都是在数据库实例下进行的。

MySQL组成

  • 连接池组件
  • 管理服务和工具组件
  • SQL接口组件
  • 查询分析器组件
  • 优化器组件
  • 缓冲组件
  • 插件式存储引擎
  • 物理文件

存储引擎

MySQL存储引擎包括:

  • InnoDB
  • MyISAM
  • NDB
  • Memory
  • Archive
  • Federated
  • Maria等。

各个引擎之间的差异主要体现在:存储容量的限制、事务支持、锁粒度、MVCC支持、支持的索引、备份和复制等。

第二章 InnoDB存储引擎

InnoDB是MySQL最常用的存储引擎。体系结构主要概括为内存和线程两项。


image.png

后台线程

  • Master Thread:缓冲区异步刷新到磁盘,保证数据一致性。包括脏页的刷新、合并插入缓冲区(INSERT BUFFER)、undo页的回收等
  • IO Thread:负责AIO(Async IO)处理写IO请求的回调处理。包括四种:insert buffer,log,read,write
  • Purge Thread:减轻Master Thread工作,负责回收已经使用并分配的undo页
  • Page Cleaner Thread:减轻Master Thread的工作和对用户查询线程的阻塞,负责脏页的刷新操作

内存

image.png

内存包括三个部分:

  • 缓冲池
  • 重做日志缓冲
  • 额外的内存池。

缓冲池

缓冲池中缓存的数据类型有:

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

其中索引页和数据页占很大一部分

缓冲池允许有多个实例,通过innodb_buffer_pool_instances配置

LRU List、Free List和Flush List

数据库中的缓冲池是通过LRU(Latest Recent Used,最近最少使用)算法来管理的。但做了修改(优化),新加入的数据放在列表的midpoint位置。
Free List保存的是当前可用的页列表
在LRU列表中的页被修改后,称该页为脏页(dirty page),即缓冲池中的页和磁盘上的页的数据产生了不一致。这时数据库会通过checkpoint机制将脏页刷新回在磁盘。所以Flush列表中的页即为脏页列表。

需要注意的是:脏页既存在于LRU列表中,页存在于Flush列表中。LRU列表用来管理缓冲池中页的可用性,Flush列表用来管理将页刷新回磁盘,二者互不影响

重做日志缓冲(redo log buffer)

通常情况,默认8M的重做日志缓冲池足以满足绝大部分的应用,因为下列三种情况会将重做日志缓冲的内容刷新到外部磁盘的重做日志文件中:

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

额外的内存池

存储一些缓冲池相关的信息,十分重要。

Checkpoint(检查点)

技术要解决的问题:

  • 缩短数据库恢复时间
  • 缓冲池不够用时,将脏页刷新到磁盘;
  • 重做日志不可用时,刷新脏页。

当数据库发生宕机时,数据库不需要重做所有的日志,因为Checkpoint之前的页都已经刷新回磁盘。故数据库秩序啊哟对Ceheckpoint后的重做日志进行恢复。这样记忆大大缩短了恢复的时间。

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

  • Sharp Checkpoint:发生在数据库关闭时将所有的脏页都刷新回磁盘
  • Fuzzy Checkpoint:只刷新一部分脏页,而不是刷新所有的脏页回磁盘

在InnoDB存储引擎中,通过LSN(Log Sequence Number)来标记版本。LSN时8个字节的数字(64位)。每个页有LSN,重做日志中也有LSN,Checkpoint也有LSN。

Fuzzy Checkpoint可能发生在以下几种情况:

  • Master Thread Checkpoint
  • FUSH_LRU_LIST Checkpoint
  • Async/Sync Flush Checkpoint
  • Dirty Page too much Checkpoint

Master Thread工作方式

InnoDB的关键特性

插入缓冲

两次写

自适应哈希索引

异步IO

刷新邻接页等

第三章 文件

InnoDB存储引擎表中包含的文件种类:参数文件、日志文件、socket文件、pid文件、MySQL表结构文件、存储引擎文件。

InnoDB存储引擎文件

重做日志文件

采用多个文件循环写的目的:写满的日志可以进行归档另存为等操作,但一般都没有归档。

当数据库主机由于掉电导致实例失败,InnoDB存储引擎会使用重做日志恢复到掉电之前的时刻,来保证数据的完整性。

第四章 表

索引组织表

当没有显示定义主键时:

  • 选取表中第一个定义的 非空 唯一索引为主键
  • 若没有上述索引,则自动创建一个6字节大小的指针。

但采用单列唯一非空索引作为主键时,可以使用_rowid搜索出来。多列索引则不能使用这个列名称。

InnoDB逻辑存储结构

image.png

InnoDB逻辑空间最高层为表空间。表空间向下可层层划分为:

  • 段(Segment)
  • 区(Extent)
  • 页(Page)/块(block)

表空间

表空间可以看作是InnoDB存储引擎逻辑结构的最高层,所有数据都存放在表空间中。

innodb_file_per_table=1可以让每张表内的数据单独存放到一个表空间内。每张表空间内存放的只是:

  • 数据
  • 索引
  • 插入缓冲Bitmap页

但是:
其他类的信息还是存放在原来的共享表空间内,例如:

  • 回滚(undo)信息
  • 插入缓冲索引页
  • 系统事务信息
  • 二次写缓冲(Double write buffer)

表空间由段组成,常见的段有:

  • 数据段(B+树的叶子结点)
  • 索引段(B+树的非索引节点)
  • 回滚段

由连续页组成,每个区大小为1MB,默认InnoDB存储引擎页大小为16KB,即一个区中共有64个连续的页。此外页的大小可以设置,所以一个区中页的各种会变化,但区的大小总是1MB。

页是InnoDB磁盘管理的最小单位。可以通过innodb_page_size设置页的大小:4K, 8K, 16K
在InnoDB存储引擎中,常见的页类型有:

  • 数据页(B-tree Node)
  • undo页(undo Log Page)
  • 系统页(System Page)
  • 事务数据页(Transaction system Page)
  • 插入缓冲位图页(Insert Buffer Bitmap)
  • 插入缓冲空闲列表页(Insert Buffer Free List)
  • 未压缩的二进制大对象页(Uncompressed BLOB Page)
  • 压缩的二进制大对象页(Compressed BLOB Page)

InnoDB存储引擎是面向行的(row-oriented)

InnoDB行记录格式

  • Compact
  • Redundant格式为了兼容旧版

Compact行记录格式

image.png

NULL标志位使用位来表示后续列中哪些是NULL,默认是1字节,但列增多的话会继续以1字节位单位扩充,高位补零。所以NULL的列越多,专门用来记录NULL需要的字节越多。不建议将字段设置可以为NULL

行溢出数据

一般情况下,InnoDB存储引擎的数据都是存放在页类型为B-tree node中,但当发生行溢出时,数据存放在页类型为Uncompress BLOB页中。

第五章 索引与算法

如果索引太多,应用程序的性能可能会收到影响,而索引太少,对查询性能又会产生影响。

InnoDB存储引擎索引概述

InnoDB存储引擎支持:

  • B+树索引
  • 全文索引
  • 哈希索引

B+树

B+树是为磁盘或者其他直接存取辅助设备设计的一种平衡查找树。

维持平衡的策略

  • 拆分页:当页满的时候
  • 旋转:当前页满,但左右兄弟节点没有满。减少了页的拆分操作,同时树的高度依然不变

Cardinality值

Cardinality表示索引中不重复记录数量的预估值。在实际应用中,Cardinality/n_rows_in_table应尽可能接近1。

InnoDB存储引擎的Cardinality统计

Cardinality的统计是放在存储引擎层进行的。
仅在INSERT和UPDATE两个操作中可能发生更新:

  • 表中的1/16的数据已经发生过变化
  • stat_modified_counter > 2 000 000 000
    更新的计算是通过采样计算

B+树索引的使用

不同应用中B+树索引的使用

根据需求设计索引

联合索引

如果没有排序需求,查询优化器优先使用单个值的索引,因为同样大小的页上可以存放更多的记录。如果有两个条件,第二个是排序的则会使用联合索引。

覆盖索引

从辅助索引中就可以得到查询的记录,而不需要查询聚集索引中的记录。
好处是:

  • 覆盖索引不包含整行记录的所有信息,故其大小要远小于聚集索引,因此可以减少大量的IO操作。
  • 执行select count(*) from buy_log; 操作时,使用辅助索引数据量比较小,可以减少IO操作

对于索引(a,b)当查询b的范围统计时,有可能使用。虽然b在索引的第二个字段。

优化器选择不使用索引的情况

对于不能进行索引覆盖的情况,优化器选择辅助索引的情况是,通过辅助索引查找的数据是少量的。这是由于当前传统机械硬盘的特性所决定的,即利用顺序读来替换随机读的查找。

如果使用固态硬盘,可以使用force index来强制使用某个索引

索引提示

Select a,b from t USER INDEX(a) where a = 1 and b = 2; 建议使用索引a,但优化器可能不听。
Select a,b from t FORCE INDEX(a) where a = 1 and b = 2; 强制使用索引a。

Multi_Range Read 优化

先查到辅助索引和对应的RowID缓存到内存中,按照RowID排序,再查询聚集索引时就变成了尽量的顺序访问了。

Index Condition Pushdown(ICP)优化

在使用索引获取数据的同时使用where条件过滤数据。将过滤操作尽量放在存储引擎层。

哈希算法

InnoDB存储引擎中的哈希算法

对于缓冲池哈希表来说,在缓冲池中的Page页都有一个chain指针,指向相同哈希函数值的页。使用除法散列计算槽的位置,而槽的个数先泽略大于2倍缓冲池页数量的质数。

选质数是为了散列更均匀,算法导论上有讲。

自适应哈希索引

全文检索

概述

从InnoDB 1.2.X版本开始,InnoDB存储引擎开始支持全文索引,其支持MyISAM存储引擎的全部功能,并且还好支持其他一些特性。

InnoDB全文索引

Full Inverted Index,表现形式为{单词, (单词所在文档的ID, 在具体文档中的位置)}
InnoDB支持的全文索引采用Full Inverted Index

全文检索

相关性计算:

  • word是否在文档中出现
  • word在文档中出现的次数
  • word在索引列中的数量
  • 多少个文档包含该word

Elasticsearch相关度计算(评分):

  • 词频
  • 逆向文档频率
  • 文档长度归一值

ElasticSearch相关性打分机制

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容