zoukankan      html  css  js  c++  java
  • InnoDB存储引擎

    InnoDB是现在使用的最多的储存引擎了吧。来看看它的特点:

    ACID事务

    行锁

    MVCC

    外键

    一致性非锁定读

    不支持全文索引

     

    InnoDB的体系架构

    主要是由内存块组成的内存池。

    内存池的主要工作

    1.维护内部数据结构

    2.缓存重做日志

    3.缓存磁盘上的数据,数据进入内存之前就存储在这里

    后台线程负责刷新内存池,保证内存池中的缓存数据是最新的。

    还有,将已经修改的数据存储到磁盘中。

     

    后台线程

    默认情况下,InnoDB有7个线程:4个IO线程、1个master 线程、1个错误监控线程、一个锁监控线程。

    4个IO线程分别是:

    insert buffer thread

    log thread

    read thread

    write thread

    在Linux系统中,IO线程的数量是不能调整的,但是在插件版的InnoDB中,read和write线程增加到了4个,

    并且配置文件中没有innodb_file_io_threads这个参数。

    --------
    FILE I/O
    --------
    I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
    I/O thread 1 state: waiting for completed aio requests (log thread)
    I/O thread 2 state: waiting for completed aio requests (read thread)
    I/O thread 3 state: waiting for completed aio requests (read thread)
    I/O thread 4 state: waiting for completed aio requests (read thread)
    I/O thread 5 state: waiting for completed aio requests (read thread)
    I/O thread 6 state: waiting for completed aio requests (write thread)
    I/O thread 7 state: waiting for completed aio requests (write thread)
    I/O thread 8 state: waiting for completed aio requests (write thread)
    I/O thread 9 state: waiting for completed aio requests (write thread)

    参数换成了innodb_read_io_threads和innodb_write_io_threads

    mysql> show variables like 'innodb_version'G;
    *************************** 1. row ***************************
    Variable_name: innodb_version
            Value: 5.6.36
    1 row in set (0.00 sec)
    
    ERROR: 
    No query specified
    
    mysql> show variables like 'innodb_%io_threads'G;
    *************************** 1. row ***************************
    Variable_name: innodb_read_io_threads
            Value: 4
    *************************** 2. row ***************************
    Variable_name: innodb_write_io_threads
            Value: 4
    2 rows in set (0.00 sec)

     

    内存

    InnoDB引擎的内存由以下几部分组成:

    缓冲池

    mysql> show variables like 'innodb_buffer_pool_size'G;
    *************************** 1. row ***************************
    Variable_name: innodb_buffer_pool_size
            Value: 134217728
    1 row in set (0.00 sec)

     

    重做日志缓冲池

    mysql> show variables like 'innodb_log_buffer_size'G;
    *************************** 1. row ***************************
    Variable_name: innodb_log_buffer_size
            Value: 8388608
    1 row in set (0.00 sec)

     

    额外的内存池

    mysql> show variables like 'innodb_additional_mem_pool_size'G;
    *************************** 1. row ***************************
    Variable_name: innodb_additional_mem_pool_size
            Value: 8388608
    1 row in set (0.00 sec)

     

    缓冲池占用的内存最大,用来缓存数据。

    存储引擎工作方式:

    将数据库文件按页(16K)读取到缓冲池中,然后按照最少使用(LRU)算法来保留缓冲池中的数据。

    如果数据需要修改,优先修改缓冲池中的数据,修改后的页叫做脏页。

    最后后台线程将脏页刷新到文件中。

     

    mysql> show engine innodb statusG;

    每个帧为16K,所以缓冲池大小为8192*16/1024=128M。

    Free buffers 当前空闲的缓冲帧数量。

    Database pages 已经使用的缓冲帧

    Modified db pages 脏页的数量

    从上面的数据可以看出,缓冲池还剩下5.5%左右可以使用。数据库压力比较大。

    Per second averages calculated from the last 30 seconds

    该命令显示的是过去30秒的状态,并非最新的状态。

     

    数据页的类型

    索引页

    数据页

    undo页

    插入缓冲(insert buffer)

    自适应哈希索引(adaptive hash index)

    InnoDB存储的锁信息(lock info)

    数据字典信息(data dictionary)

     

    日志缓冲将日志文件先放入缓冲区,然后刷新到重做日志。一般每秒就会将重做日志缓冲刷新到日志文件,日志缓冲的值不需要设置很大,大于每秒的事务量即可。

     

    InnoDB引擎管理内存的方式叫做内存堆(heap)

    在对某些数据结构本身进行内存分配时,首先从额外内存池分配,不够用就从缓冲池分配。

    InnoDB实例的缓冲池中,缓冲帧对应的缓冲控制对象所需的内存也是从额外内存池分配的,

    所以当缓冲池很大时,额外内存池的大小也要增加。

     

    master thread

    InnoDB引擎的主要工作都是在master thread由完成的。

    master thread线程的优先级最高,通过分析其源代码可以知道,其内部由几个循环构成:

    主循环(loop)

    后台循环

    暂停循环

    刷新循环

    master thread基本就是在这几个循环之间来回切换。

     

    主循环(loop)

    大部分操作都在此循环中完成,分为2大部分:每秒钟的操作和每10秒的操作

     

     从代码中可以看出,是可能有延迟的。

    每一秒的操作包括:

    重做日志缓冲刷新到磁盘,即使这个事务还没有提交(总是)。

    合并插入缓冲(可能)。

    最多刷新100个InnoDB缓冲池中的脏页到磁盘(可能)。

    如果当前没有用户活动,切换到后台循环(可能)。

    即使事务没有提交,重做日志缓冲每秒也会被刷新到磁盘中的重做日志文件,这也是为什么再大的事务提交的时间也很快。

     

    合并插入缓冲并不是每秒都发生。InnoDB引擎会判断一秒内发生的IO次数是够小于5次,如果小于5次,InnoDB认为IO压力很小,

    就会执行插入缓冲合并。

     

    同样,最多刷新100个脏页也不是一定发生。InnoDB会判断当前缓冲区脏页的比例是否超过了配置文件中innodb_max_dirty_pages_pct

    参数(默认90%),如果超过了该值,就会刷新100个脏页到磁盘中。

     

    接着来看每10秒的操作:

    刷新100个脏页到磁盘(可能)。

    合并至多5个插入缓冲(总是)。

    将日志缓冲刷新到磁盘(总是)。

    删除无效的重做页(总是)。

    刷新100个或者10个脏页到磁盘(总是)。

    产生一个检查点(总是)。

    以上过程中,InnoDB首先会判断过去10秒内,IO操作是否超过200次,

    如果没有,将会把100个脏页刷新到磁盘。

    之后,会合并插入缓冲。

    之后,会将日志缓冲刷新到磁盘。

    然后,删除无用的Undo页。

    在执行update或者delete操作时,因为一致性读的关系,这些行的版本信息会被保留,

    在进行Undo时,会去判断这些被删除的行是否可以删除

    如果可以,立即删除。通过源代码可以知道,最多一次删除20个Undo页

    然后,InnoDB回去判断缓冲池中脏页的比例,如果大于70%,则刷新100个脏页,否则,刷新10个脏页

    最后,InnoDB会产生一个检查点,在此刻,InnoDB会将最老日志序列号(oldest LSN)的页写入磁盘。

     

    接着来看后台循环

    如果数据库没有活动,数据库空闲或者数据库关闭时,就会切换到这个模式。

    这个循环会执行的操作:

    删除无用的Undo页(总是)。

    合并20个插入缓冲(总是)。

    跳回到主循环  (总是)。

    不断刷新100个页,知道符号条件(可能,跳转到flush loop中完成)

    如果刷新循环没有什么活动,会切换到暂停循环,将master thread挂起。

    如果启用了InnoDB引擎,却没有任何基于InnoDB的表,就是处于这个状态。

     

    master thread的潜在问题

    从上面的知识可以知道,源代码对IO做了限制。每秒最大刷新100个脏页或者刷新20个插入缓冲。

    这个可能在某些程序中会导致master thread忙不过来

    所以在InnoDB Plugin版本中加入了innodb_io_capacity参数,

    用来表示磁盘IO吞吐量

    mysql> show variables like 'innodb_io%'G;
    *************************** 1. row ***************************
    Variable_name: innodb_io_capacity
            Value: 200

    规则如下:

    在合并插入缓冲时,数量为该值的5%

    在刷新脏页时,数量为该值

     

    如果使用了SSD和进行了Raid操作,可以将该值设置的高点。

     

    另一个问题是参数innodb_max_dirty_pages_pct,在mysql5.1(包括此版本),默认值为90%,

    意味着脏页占缓冲池的90%,这个太大了!在InnoDB Plugin版本,该值被调整为了75%,

    所以可以兼顾脏页刷新频率和磁盘IO。

     

    InnoDB Plugin的另一个参数是innodb_adaptive_flushing(自适应的刷新),该值影响每秒脏页的数量

    mysql> show variables like 'innodb_adaptive_%'G;
    *************************** 1. row ***************************
    Variable_name: innodb_adaptive_flushing
            Value: ON

    这个参数会导致,当脏页在缓冲池的比例小于innodb_max_dirty_pages_pct时,也会刷新一定数量的脏页。

    所以,最好使用InnoDB Plugin版本,对数据库的性能会有提升。

     

    关键特性

    InnoDB的关键特性还包括插入缓冲,2次写,自适应哈希索引。

    插入缓冲

    我们知道,主键是行的唯一标识符,在表中,行的插入顺序是按照主键递增的

    插入缓冲的使用要满足2个条件

    索引是辅助索引

    索引不是唯一的

     

    2次写

    这个可以保证数据的可靠性。

    架构

     当脏页刷新时,并不是直接将其写入磁盘,而是先将其写入内存中的doublewrite buffer。

    每次写入1M到共享表空间的磁盘中。这样如果数据库崩溃了,可以在共享表空间找到页的副本,

    在应用重做日志来恢复。

    自适应哈希索引

    哈希是一种快速的查找方法。

    常用语join操作

    InnoDB引擎会监控表上的索引查找,如果观察到建立哈希索引会带来速度的提升,

    就会建立哈希索引,这就是自适应哈希索引。

    启动自适应哈希索引,可以带来读写性能2倍的提高;

    可以带来辅助索引性能5倍的提高;

    -------------------------------------
    INSERT BUFFER AND ADAPTIVE HASH INDEX
    -------------------------------------
    Ibuf: size 1, free list len 0, seg size 2, 0 merges
    merged operations:
     insert 0, delete mark 0, delete 0
    discarded operations:
     insert 0, delete mark 0, delete 0
    Hash table size 276707, node heap has 402 buffer(s)
    0.00 hash searches/s, 0.00 non-hash searches/s

    默认开启

    *************************** 3. row ***************************
    Variable_name: innodb_adaptive_hash_index
            Value: ON

    启动、关闭和恢复

     innodb_fast_shutdown参数影响InnoDB引擎的行为,默认为1

    mysql> show variables like 'innodb_fast_shutdown'G;
    *************************** 1. row ***************************
    Variable_name: innodb_fast_shutdown
            Value: 1
    1 row in set (0.00 sec)

    0 表示关闭数据库时,需要完成所有的full purge和merge insert buffer操作

    如果在升级InnoDB Plugin,可以将该值设置为0

    2 表示不完成full purge和merge insert buffer操作,也不将缓冲池中的数据脏页写会磁盘,而是写在日志。

    innodb_force_recovery参数影响引擎的恢复情况,默认值为0
    mysql> show variables like 'innodb_force_recovery'G;
    *************************** 1. row ***************************
    Variable_name: innodb_force_recovery
            Value: 0
    1 row in set (0.00 sec)

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    Chrome使用指南
    Vue2.x-踩坑记
    C# WinForm listView 多行删除 操作
    Winform中DataGridView多行删除
    20211026_阿里云服务器引流限制ssl的问题
    docker commit
    docker build
    docker build与docker commit
    阿里云Docker镜像仓库(Docker Registry)
    Docker Nginx安装(centos7)
  • 原文地址:https://www.cnblogs.com/leomei91/p/7516172.html
Copyright © 2011-2022 走看看