《MySQL技术内幕:InnoDB存储引擎》第二章 InnoDB存储引擎

2.1 概述

  • Innobase Oy 公司开发
  • 第一个完整支持ACID事务的MySQL存储引擎(BDB是第一个支持,黄了),行锁设计,支持MVCC,提供类似Oracle风格的一致性非锁定读,支持外键,被设计用来最有效地利用内存和CPU
  • Heikki Tuuri是创始人
  • 适合OLTP(联机事务处理 On-Line Transaction Processing,对比联机分析处理 On-Line Analytical Processing)项目

2.2 InnoDB体系架构

InnoDB体系结构

多个内存块组成的内存池负责如下:

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

后台线程主要负责:

  • 刷新内存池中的数据
  • 保证缓存池中的内存缓冲的是最近的数据
  • 将已修改的数据文件刷新到磁盘文件
  • 保证在数据库发生异常时InnoDB能恢复到正常运行状态

2.2.1

Oracle是多进程架构,核心后台进程有CKPT、DBWn、LGWR、ARCn、PMON、SMON等
而InnoDB不是,它是在master thread线程上实现了所有的功能。
默认情况下,InnoDB后台线程有7个,4个IO线程,一个master thread,一个锁监控线程,一个错误监控线程。
4个IO thread为 insert buffer thread,log thread,read thread,write thread,InnoDB Plugin版本后不再用innodb_file_io_threads参数控制read thread 和write thread数量,而是使用 innodb_read_io_thread和innodb_write_io_thread

使用此命令查看后台线程

show engine innodb status\G

2.2.2 内存

InnoDB由缓冲池(buffer pool)、重做日志缓冲池(redo log pool)、以及额外的内存池(additional memory pool),分别由innodb_buffer_pool_size、innodb_log_buffer_size 和 innodb_additional_mem_pool_size 的大小决定。

show variables like 'innodb_buffer_pool_size';
InnoDB存储引擎内存结构
  • 缓冲池是占最大内存的部分,用来存放各种数据的缓存。InnoDB将数据库文件按页(16K,对应一帧)读取到缓冲池,然后按最近最少使用算法管理缓存数据。数据库文件修改后则先改缓存,定期刷新(flush)到文件
  • 日志缓冲将重做日志信息存入缓存区,一般每秒刷新到日志文件一次,所以其大小需要满足一秒内的事务量
  • 额外内存池也很重要,缓冲池中的帧缓冲还有对应的缓冲控制对象(记录了诸如LRU、锁、等待等方面的信息)都存储在额外内存池中,所以需要跟随缓冲池大小而变动

2.3 master thread

2.3.1 master thread 源码分析

master thread 线程级别最高,其内部由主循环(loop),后台循环(background loop),刷新循环(flush loop),暂停循环(suspend loop),master thread根据数据库运行状态在这几个循环中切换,loop主要有两大部分,每秒操作,每10秒操作:

void master_thread(){
   loop;
   for(int i = 0;i < 10;i++){
      do thing once per second
      sleep 1 second if necessary
   }
   do things once per 10 second
   goto loop;
}

每秒一次操作包括:

  • 日志缓冲刷新到磁盘,即使这个事务还没有提交(总是),所以再大的事物commit的时间也是很快的
  • 合并插入缓存(可能),当前一秒IO次数少于5次时发生
  • 至多刷新100个InnoDB的缓冲池中的脏页到磁盘(可能),通过判断当前缓冲池中的脏页比例(buf_get_modified_ratio_pct)是否超过配置文件中的innodb_max_ditry_pages_pct,默认为90,如果超过则执行。
  • 如果当前没有活动,切换到background loop

每10秒一次操作包括:

  • 刷新100个脏页到磁盘(可能)
  • 合并至多5个插入缓冲(总是)
  • 将日志缓冲刷新到磁盘(总是)
  • 删除无用的Undo页(总是)
  • 刷新100个或者10个脏页到磁盘(总是)
  • 产生一个检查点(总是)

然后是background loop,若当前没有用户活动,则进入此处

  • 删除无用的Undo页(总是)
  • 合并20个插入缓冲(总是)
  • 跳回到主循环(总是)
  • 不断刷新100个页,直到符合条件(可能,跳转到flush loop中完成)

若是flush loop中也没有事儿,则转入 suspend loop,挂起master thread,等待事件

2.3.2 master thread 的潜在问题

  • 随着硬件性能的增强,缓冲池到磁盘硬性规定刷新100个脏页可能浪费硬件资源,故引入innodb_io_capacity,表示磁盘吞吐量,可根据磁盘性能设置,刷新脏页时会按比例刷新
  • innodb_max_dirty_pages_pct默认值90不妥,太大了,经测试,75更妥,并引入innodb_adaptive_flushing(自适应的刷新,决定每1秒刷新的脏页数),这个参数的引入,通过buf_flush_get_desired_flush_rate 这个函数来判断需要刷新的脏页数,其原理是通过判断产生重做日志的速度来判断最合适的刷新脏页的数量。

2.4 关键特性

2.4.1插入缓冲(插入性能)

主键是行唯一的标识符,程序中插入记录顺序是按主键递增的,因此插入聚集索引一般是顺序的,不需要磁盘的随机读取。而非聚集索引的插入是离散的,B+树特性而至。
插入缓冲有两个条件

  • 索引是辅助索引
  • 索引不是唯一的

但是当程序执行大量的插入和更新操作,此时数据库又宕机,将会有大量的插入缓冲没有合并到实际的非聚集索引中,花费大量时间恢复。
辅助索引不能使唯一的,因为插入到插入缓冲时,我们并不去查找索引页的详情,吐过去查看了则又出现离散读,插入缓冲则失去意义。
插入缓存占用太多缓冲池内存时,调整IBUF_POOL_SIZE_PER_MAX_SIZE 即可

2.4.2 两次写 (可靠性)

InnoDB存储引擎doublewrite架构

脏页刷新时,先memcpy拷贝到内存中的doublewrite buffer中,然后通过doublewrite buffer分两次,每次1MB写入共享表空间的物理磁盘(doublewrite页连续,开销较小),然后将doublewrite buffer中的页写入表空间文件(此时为离散的,开销大)。如果写入磁盘过程中崩溃了,则可以从doublewrite页拷贝页的副本到表空间文件,再用重做日志进行恢复。skip_innodb_doublewrite可以禁止两次写功能

2.4.3 自适应哈希索引

  • 自适应哈希索引通过引用缓冲池的B+树构造而来,因此建立的速度很快。
  • InnoDB存储引擎会自动根据访问的频率和模式来为某些页建立哈希索引。
  • 自适应哈希索引只能用来搜索等值条件的查询。
  • 可以通过 innodb_adaptive_hash_index开禁用和启动

2.5 启动、关闭与恢复

参数innodb_fast_shutdown 取值

  • 0 当mysql关闭时,InnoDB需要完成所有的full purge 和 merge insert buffer
  • 1 为默认值,表示不完成full purge 和 merge insert buffer,但是脏页数据还是会刷新到磁盘
  • 2 不完成full purge 和 merge insert buffer,脏页数据也不会刷新到磁盘,但是下次启动时,数据库会执行恢复操作。

参数 innodb_force_recovery 取值

  • 0 默认值,恢复时执行所有的回复操作
  • 1 忽略检查到的corrupt页
  • 2 阻止主线程运行,入主线程需要执行full purge操作,会crash
  • 3 不执行事务回滚
  • 4 不执行插入缓冲的合并操作
  • 5 不查看撤销日志,将未提交事务视为已提交
  • 6 不执行前滚的操作
    需要注意的是,当设置参数大于0后,可以对表进行select、create、drop操作,但是insert、update、和delete这类操作是不允许的

2.6 InnoDB Plugin = 新版本的InnoDB存储引擎

mysql 5.1这个版本,采用了插件式的架构,这样,如有存储引擎的bug,无需再等待mysql的新版本了。
InnoDB新功能

  • 快速索引重建
  • 更好的多核性能
  • 新的页结构
  • 页压缩功能
  • 更好的BLOB处理能力

欢迎大家关注我的公众号


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

推荐阅读更多精彩内容