第二章 InnoDB储存引擎(上)

2018-12-29  本文已影响0人  正在加载更多
2.1 InnoDB存储引擎概述

该引擎是第一个完整支持ACID事务的MySQL存储引擎,其特点是行锁设计,支持多版本并发控制(MVCC),支持外键,提供一致性非锁定读。InnoDB是一个高性能,高可用,高可拓展的存储引擎

2.2 InnoDB存储引擎的版本
InnoDB各版本比较.png
2.3 InnoDB体系架构

InnoDB存储引擎有多个内存块,负责如下工作:

2.3.1 后台线程
  1. Master Thread 。主要负责将缓冲池中的数据异步的刷新到磁盘,保证数据的一致性,包括脏页的刷新,合并插入缓冲,UNDO页的回收等。
  2. IO Thread 。在InnoDB引擎中大量使用的AIO来处理IO请求,而IO Thread的主要工作就是这些IO请求的回调处理。有四种IO Thread,分别是write,read,insert buffer和log ,在linux平台,IO Thread数量不能调整,window下可以使用innodb_read_io_threads 和innodb_write_io_threads进行设置
  3. Purge Thread。事务被提交之后,其所使用的undo log可能不再需要了,因此需要Purge Thread来回收已经使用并分配的undo页。用户可以通过配置
[mysqld]
innodb_purge_threads = 1

来独立启动Purge Thread

  1. Page Cleaner Thread。把脏页刷新到磁盘,减轻Master Thread的工作以及对用户查询线程的阻塞
2.3.2 内存
InnoDB内存数据对象.png
  1. 缓冲池
           InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。对于数据库中页的修改操作,则首先修改在缓冲池中的页,然后再以一定的频率刷新到磁盘上。为了提升整体的性能,并不是每次更新页中的数据就刷新数据到磁盘,而是通过一种checkpoint的机制来刷新。
           缓冲池不止有数据页和索引页,他们只是占据了大部分而已。从InnoDB 1.0.x开始,允许有多个缓冲池实例。每个页根据哈希值平均分配到不同的缓冲池实例中。可以通过参数 innodb_buffer_pool_instances来配置,可以通过
show engine innodb status

或者

select * from  innodb_buffer_pool_status  <!--从5.6版本开始-->

来查看缓冲池的状态

  1. LRU List 、Free List和Flush List
            缓冲池是一个很大的内存区域,其中存放了各种类型的页,页的大小默认是16K,并且通过LRU(Last Recent Used,最近最少使用)算法来进行管理,即使用最频繁的页在LRU列表的前端,使用最少的页放到LRU列表的尾端。当缓冲池不能存放新读取到的页的时候,将先释放LRU列表中尾端的页。InnoDB引擎对传统的LRU算法做了优化,加入了midpoint位置,新读取到的页,不直接放入LRU列表的首部,而是放到minpoint的位置,默认是5/8,可以通过 innodb_old_blocks_pc 控制。midpoint之前的列表成为new列表,之后的列表成为old列表。
    不采用传统的LRU算法的原因是避免像全表扫描之类的查询操作(查询出来的数据只用一次或者几次的)将真正的热点数据从LRU列表移除。可以通过参数 innodb_old_blocks_time来控制页读取到midpoint位置后需要等待多久才会被加入到LRU列表的热端
            LRU列表用来管理已经读取的页,Free列表用来管理空闲页,当数据库刚启动时,LRU列表是空的,页都在Free列表中。当需要从缓冲池中分页时,首先从Free列表中查找是否有可用的空闲页,若有,则将该页从Free列表删除,放入到LRU列表中。负责,根据LRU算法,淘汰掉LRU列表末尾的页,再将该内存空间分配给新的页。InnoDB存储引擎从1.0x版本开始支持压缩页的功能,即将原来16KB的页压缩为1KB,2KB,4KB和8KB。对于非16KB的页,通过unzip_LRU列表进行管理。
            unzip_LRU从缓冲区申请4KB大小的页的步骤如下:
             a)检测4KB的unzip_LRU列表,坚持是否有可用的空闲页
             b)若有,则直接使用
             c)否则,坚持8KB的unzip_LRU列表
             d)若能够得到空闲页,将页分成2个4KB的页,存放到4KB的unzip_LRU列表
             e)若不能得到空闲页,从LRU列表中申请一个16KB的页,将页分成一个8KB和两个4KB的页,分别存放到对应unzip_LRU列表

        在LRU列表中的页被修改后,称该页为脏页(dirty page),即缓冲区中的页和磁盘上的页的数据产生了不一致。这是数据库会通过CHECKPOINT机制将脏页刷新回磁盘,而Flush列表中的页即为脏页列表。LRU列表用来管理缓冲池中页的可用性,Flush列表用来管理将页刷新回磁盘,二者互不影响。

3.重做日志缓冲(redo log buffer)
        InnoDB存储引擎首先将重做日志信息先放入到这个缓冲区,然后按一定频率将其刷新到重做日志文件。重做日志缓冲一般不需要设置很大(由 innodb_log_buffer_size控制),重做日志是循环写的,并按照一定的策略刷新到外部磁盘的重做文件中
        a):Maste Thread 每一秒将重做日志缓冲中的内容刷新到重做日志中
        b):每个事物提交时会将重做日志缓冲刷新到重做日志中
        c):当重做日志缓冲池剩余空间小于1/2时,重做日志缓冲刷新到重做日志文件

4.额外的内存池
        在InnoDB存储引擎中,对内存的管理是通过一种称为内存堆的方式进行的。在对一些数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当该区域的内存不够时,会从缓冲池中进行申请。

2.4 Checkpoint技术

        缓存池的设计目的是为了协调cpu速度与磁盘速度的鸿沟。因此操作首先是在缓冲池中完成的。如果一条DML语句改变了页中的记录,那么此时页是脏的,即缓冲池的页的版本比磁盘中的新,数据库需要将页中的新版本刷新到磁盘中。倘若每次页发生变化就刷新到磁盘,则开销的十分大的,若热点数据集中在某几个页中,那么数据库的性能将变得非常差。同时,如果从缓冲池中将页的数据刷新到磁盘时发生了宕机,那么数据就不能恢复了。为了避免数据发生丢失的问题,当前事务数据库普遍采用WAL(Write Ahead Log)策略,即当事务提交时,先写重做日志,再修改页。当由于发生宕机而导致数据丢失时,通过重做日志来完成数据的恢复。这也是事务ACID中D(Durability持久性的要求)
        Checkpoint(检查点)技术的目的是解决以下几个问题:
        a):缩短数据库的恢复时间
        b):缓冲池不够用时,将脏页刷新到磁盘
        c):重做日志不可用时,刷新脏页
        当数据库发生宕机时,数据库不需要重做所有的日志,因为Checkpoint之前的页都已经刷新回磁盘。故数据库只需要对checkpoint后的重做日志进行恢复。这样就大大缩短了恢复的时间。
        当缓冲池不够时,根据LRU算法会淘汰掉最近最少使用的页,若此页为脏页,那么需要强制执行checkpoint,将脏页刷新回磁盘
        重做日志出现不可用的情况是因为当前事务数据库系统对重做日志的设计都是循环使用的,并不是让其无限增大的,这从成本及管理上都是比较困难的。重做日志可以被重用的部分是指这些重做日志已经不再需要,即当数据库发生宕机时,数据库恢复操作不需要这部分的重做日志,因此这部分就可以被覆盖重用。
        对于InnoDB存储引擎而言,其是通过LSN(Log Sequence Number)来标记版本的。而LSN是8字节的数字,其单位是字节,每个页是有LSN的,重做日志也有LSN,Checkpoint也有LSN。Checkpoint发生的时间,条件以及脏页的选择是十分复杂的,而Checkpoint所在的事情就是将脏页刷新回磁盘。

        在InnoDB引擎中,有两种Checkpoint,一种是Sharp Checkpoint,一种是Fuzzy Checkpoint。
        Sharp Checkout发生在数据库关闭时将所有的脏页都刷新回磁盘。
        Fuzzy Checkpoint在InnoDB引擎内部进行页的刷新,只刷新部分脏页,而不是刷新所有脏页回到磁盘。Fuzzy Checkpoint可能会在如下几种情况下发生:
        a):Master Thread Checkpoint ,差不多以每秒或者每十秒的速度从缓冲池的脏页列表中刷新一定比例的页回到磁盘。这个过程是异步。
        b):FLUSH_LRU_LIST Checkpoint,因为InnoDB存储引擎需要保证LRU列表中需要有差不多100个空闲页可供使用。InnoDB1.2.x以后,这个检查操作放在了一个单独的Page Cleaner线程中进行,并且用户可以通过参数innodb_lru_scan_depth控制LRU列表中可用页的数量,该值默认为1024。
        c):Async/Sync Flush Checkpoint ,当重做日志不可用时,这时需要强制将一些页刷新回到磁盘,而此时脏页是从脏页列表中选取的。InnoDB1.2.x以后,这个操作放在了一个单独的Page Cleaner线程中进行。Async/Sync Flush Checkpoint 保证了重做日志循环使用的可用性
        d)Dirty Page too much:脏页数量太多了,导致InnoDB存储引擎强制进行Checkpoint。可通过参数 innodb_max_dirty_pages_pct控制

上一篇 下一篇

猜你喜欢

热点阅读