美文网首页
Mysql技术内幕之读书笔记-innodb篇

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

作者: 生活有方有圆 | 来源:发表于2019-02-17 19:56 被阅读0次

    这本书的内容写的很好,排版也很好,很值得人花时间去细细品味。
    以前我只会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

    相关文章

      网友评论

          本文标题:Mysql技术内幕之读书笔记-innodb篇

          本文链接:https://www.haomeiwen.com/subject/qixovftx.html