Mysql技术内幕之读书笔记-innodb篇

这本书的内容写的很好,排版也很好,很值得人花时间去细细品味。
以前我只会sql语法,我觉得数据库还是很简单,基本逻辑我都能写呀。
直到遇到这本书,我才发现数据库的水还是很深的

目录
  • mysql体系结构框图
  • innodb结构图
  • 后台线程
    • Master Thread
    • IO Thread
    • Purge Thread
    • Page Cleaner Thread
  • 内存池
    • 缓冲池
    • 重做日志缓冲
    • 额外的内存池
    • LRU List + Free List + Flush List
    • Check Point
  • Master Thread工作内容
  • innodb 几大特性
    • 插入缓冲
    • 两次写
    • 自适应哈希
  • 命令集合
  • 磁盘基本概念
  • 性能优化相关

mysql体系结构

由于要讲innodb,所以咱们先看下innodb在mysql中的位置。

mysql 体系结构.jpg

详细的大家可以参考这篇文章:体系结构
我们会在另一篇文章里专门讲mysql的体系结构的。这里只讲Innodb存储引擎部分。
说明:Innodb是支持事务的插件式存储引擎,而且也是大家最常用的一款。

innodb结构

innodb体系结构.jpg

咱们从这里可以看出,innodb存储引擎是直接跟磁盘文件打交道的一层。
下面咱们看看Innodb具体做了什么

后台线程

  • Master Thread
    主线程算是Innodb的一个中流砥柱了吧。会做很多事情。
    主要负责将缓冲的数据同步到磁盘,包括刷新脏页,回收undo页,合并插入缓冲等。
    后面会专门讲
  • IO Thread
    输入输出线程也是个伟大的存在,就像小蜜蜂一样,是个勤劳的搬运工。
    是咱们与磁盘IO交换数据的基石。
    主要负责刷新缓冲数据到磁盘和从磁盘读取数据。
    Read IO Thread
    Write IO Thread
    Insert Buffer IO Thread
    Log IO Thread
    在1.0.x版本开始,默认情况下Read IO Thread 和 Write IO Thread的个数是4个。
    不过在Windows下可以通过参数来改变。
    Innodb_read_io_threads和Innodb_write_io_threads来控制。(之前版本用这个参数Innodb_file_io_threads控制IO数量)
    关于IO和磁盘的内容下面还是会专门讲的。
  • Purge Thread
    undo页回收线程
    可以通过参数innodb_purge_threads=N来设置线程个数
  • Page Cleaner Thread
    脏页处理线程

内存池

innodb 内存数据对象.jpg

从上图咱们可以看出,内存池被划分为缓冲池、日志缓冲、额外的内存池。

1. 缓冲池

既然这里出现了缓冲池,基本也算是生产者和消费者模型了,不过这里面的操作是相当复杂的。
咱们操作的数据也不是单一的某种类型,而是数据页、索引页、插入缓冲、自适应哈希索引、锁信息、数字字典信息等。是不是觉得很精彩呀。
由于缓冲池也算是临界区了吧,咱们一口气配了那么多IO线程来操作它,要花很多代价在等待上。所以设计人员就把缓冲池实例数量改成可配置的。允许我们配置多个。这样就减少多个线程的竞争,提高并发的能力。
那么既然缓冲池这么重要,咱们是不是要把它配大一点呀,如果太小了,我们里面的线程可是要忙死的,万一忙不过来可是会出大问题的。
innodb_buffer_pool_size可以配置缓冲池的大小。
innodb_buffer_pool_instances可以配置缓冲池实例的数量。

LRU List、Free List、Flush List

既然是个缓冲池,如果咱们不定期清理的话,很可能就会满。
从上面咱们也说过,innodb的缓冲不能配置的太小了,不然如何应对百万级、千万级的数据呢。
所以里面肯定有管理机构啦,不然咱们计算机动不动就要遍历这么个超级数据团,还不死翘翘。
第一个机构叫做Free List,管理着缓冲池中未使用的页。其实有点类似于失业人口管理所。
第二个机构叫做LRU List,管理着已经读取的页。相当于咱们每个在职人员都登记在册一样。
第三个机构叫做Flush List,管理着数据不一致的页,也即是脏页。相当于职位变更的记录。
那么这三个机构刚好构成了咱们工作的状态信息。

  • Free List
    当咱们需要找人来干活,会发布信息给Free List,希望它能够帮我们找到一个合适的人来给我们干活。

  • LRU List
    这个机构其实是一个比较实在的机构,平时可以帮我们做很多事情。
    当咱们找到人来帮我们干活时,一定会登记到这个LRU里面的。
    假如在试用期过了之后,这个人的表现还不是令人很满意,他就不能够成为热点数据。
    只能被扔到冷门的部门,这时候就可能会被优先解雇掉。

假如这次咱们要找一批兼职人员做某个活动,结果发现几个兼职人员合作能够干过一个老员工,这是老板就疯狂的招聘兼职人员,结果老员工都被顶替了。当兼职人员干完活的时候,公司就没有人可以干活了。
为了避免发生这种事情,公司就出了新的策略。
第一 为了保证员工的利益,兼职人员除非转正,且成绩优秀,才能够做重要的任务。
第二 由于公司资金有限,所以只能招聘一定数量的人员,不干活的人员要及时解雇。
第三 到底要解雇多少员工,这个要由老板说了算,不过默认是从垫底的5/8员工里挑选解雇人员的。
这个挑选范围是innodb_old_blocks_pct参数来控制的。
试用期由innodb_old_blocks_time来决定的。

当现在社会就业情况不是很好的时候,LRU管理机构决定解雇很多不干活的人,如果解雇的人中有人已经换了工作,那么它会及时把信息存档的,然后把他们都给解雇了。
这里咱们要表明一点,LRU最少要预留100个页的空位。

  • Flush List
    这个机构主要负责记录那些工作变更的人。
2. 重做日志缓冲

重做日志这东西比较重要的。还记的之前事务的时候咱们有讲过持久性吗?其实重做日志就是用来恢复数据的。所以重做日志要及时的写到磁盘上(假如重做日志设置的太小或者太大会怎么样呢)
重做日志会在以下三个情况下写入到磁盘:

  • Master Thread每秒都会进行一次刷新
  • 每个事务提交的时候都会进行一次磁盘写
  • 当缓存池空间小于一半时,进行写操作

所以按照上面的情况来讲,咱们只要保证重做日志缓冲区的大小,满足每秒并发的事务量就好了。
日志缓冲区的大小由innodb_log_buffer_size决定。

3. 额外内存池

//todo

checkpoint

明眼人一听这个名字,就知道这肯定时一个比较强势、权威的机构了。
checkpoint 检查点,我觉得可以理解为巡逻点。
目的是为了维护咱们周边环境的治安,降低各种天灾人祸带来的损失。
专业来说是,为了缩短数据库宕机后的恢复时间。
刷新脏页到磁盘。
那么问题来了,这个机构啥时候要发发威,做做事呢。
其实他们是很懒的,也是比较被动的。

  • 上级发现很多脏页,让他们去处理一下。这时他们才会去找Flush List要脏页信息,然后将其刷新到磁盘。
    innodb_max_dirty_pages_pct控制最大脏页的比例。

  • 下面出场的这个机构其实也不能叫啥机构,不过比较喜欢管事情,而且还管杂七杂八的事情。我觉得应该叫他社会舆论吧。这群家伙闲的很,经常会去做各种调查,然后报告给checkpoint,checkpoint无奈之下只能去Flush List找相应的脏页信息然后刷新。
    忘记说了,这个东西叫做Master Thread

  • LRU List这个机构,上面说了相当于一个人事啦,它发现现在社会上大部分的工作都已经被人应聘了。可能只剩下100个岗位空缺了,这时候他就很着急,就会去解雇一些不干活的人,解雇的同时如果他发现脏页,也会叫check point来清理。
    当然这个空闲岗位的数量也是可以由我们自己来定的。
    innodb_lru_scan_depth来控制。

  • 最后一个可能会比较难理解,咱们知道,为了保证数据的可恢复性,必须要先把日志写到日志文件,然后才会把数据更新到磁盘。
    因为咱们日志文件的大小不是无限大的,所以会导致一些历史悠久的日志要被删除。那么假如在删除这部分日志文件之前,发现相应的数据还是没有同步到磁盘,那么就要赶紧发起check point,让他去脏页列表中,把我们要同步的数据给刷到磁盘。
    到底什么时候要刷新我们要的脏页呢,看下面的规矩。
    大体如下:
    假如咱们还没有同步的数据<日志文件大小的百分之70,那么不着急找Check point.
    假如大于百分之70小于百分之90,那么就异步刷新咱们要的数据。
    如果大于百分之90,那么要全力刷新咱们要的数据了。

这个刷新操作在Page Cleaner Thread中执行。

Master Thread的工作内容

上面咱们说过,Master Thread相当于社会舆论。他会做很多事情,比较杂乱。
分为4个主要部分:

  • Loop
    由每秒循环和10秒循环构成。
    重要的东西会每秒去执行,比如重做日志刷新。
    其他的每秒可能执行内容包括:插入缓冲合并,脏页刷新
    当脏页的比例超过设置的阈值时,比如默认是百分之75,则会刷新100个脏页到磁盘。
    当前一秒的IO执行不超过5次,那么innodb会认为当前io压力不是很重,将会执行插入缓冲合并。

每十秒执行内容:重做日志刷新、合并5条插入缓冲、假设脏页的数量小于百分之70,刷新百分之10的脏页到磁盘,如果脏页的数量大于百分之70,刷新100个脏页到磁盘。还会判断过去10秒内的IO操作是否小于200次,如果小于的话,还会刷新100个脏页到磁盘。会回收最多20个undo页。

  • backgroup Loop
    若当前没有用户活动 或者数据库关闭,那么会切换到这个后台循环。
    后台循环总是会去删除无用的undo页。
    总是会合并20条插入缓冲。
    总是会跳到主循环。
    总是会刷新100个脏页直到符合条件----可能会在Flush Loop中执行。

  • flush loop

  • suspend loop
    当上面的循环都没有事情做了,那么就会跳到暂停循环了。

上面咱们讲的是1.0.x之前的版本。
下面来讲下1.0.x对Master Thread所做的改变。
由于之前刷新多少脏页,合并多少插入缓冲,回收多少无用Undo页,都是写死的。
随着咱们现在硬盘技术的提升,IO的处理能力已经大大的提升了。所以咱们就提供了参数,可以让用户根据相应的硬件设备来修改这些值,以达到最大的吞吐量。
innodb_io_capacity这个值会影响合并插入缓冲和刷新脏页的数量。
合并插入缓冲数量=innodb_io_capacity * 5%;
脏页刷新数量=innodb_io_capacity;

innodb_adaptive_flushing 会影响每秒脏页刷新的数量。叫做自适应刷新,他的判断依据是通过判断重做日志产生的速度,来决定每秒要刷新多少脏页。
默认是开启的。

innodb_purge_batch_size这个参数是决定一次回收多少undo页。
默认是20

几大特性

  • 插入缓冲
    由于不知道索引在磁盘中的存储结构,及表的机构,所以这个点先不讲
    //todo

  • 两次写
    在写这个点之前,我们先了解下日志文件记录的内容。
    mysql日志文件是逻辑型的。
    逻辑性日志文件:即我要向某个表空间写入一条数据。
    而不是记录我正在想磁盘上某个地方写一个值,还有多少值没写之类的吧。

那么正当我从内存池把一个页的数据写到磁盘的中途,突然断电了。那么这时候假设就只有半个页写进去。这就叫做部分写失效。
当发生部分写失效的时候,下次上电咱们去进行数据恢复,发现有个页数据不一致,也就是我们那个被多写半个页的家伙。这个不上不下的家伙,就找不到自己日志的相应点了,因为日志里并没有标记我已经执行了多少,然后还有多少没执行。
所以innodb就搞个两次写来。也就是我写数据页之前,先备份一份数据页。

  • 自适应哈希
    这个点也到后面索引之后再讲
    //todo

命令集合

线程相关:
innodb_read_io_threads
innodb_write_io_threads
innodb_purge_threads
缓冲相关:
innodb_buffer_pool_size
innodb_buffer_pool_instances
LRU相关:
innodb_old_blocks_pct
innodb_old_blocks_time
innodb_lru_scan_depth
脏页相关:
innodb_max_dirty_pages_pct
重做日志:
innodb_log_buffer_size
Master Thread刷新量相关:
innodb_io_capacity
innodb_adaptive_flushing
innodb_purge_batch_size

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

推荐阅读更多精彩内容