Innodb

在这里插入图片描述

  • 索引

    • b+树索引
    • 全文树索引
    • 哈希树索引
  • 特性

  • 支持事务

  • 行锁设计、支持外键

  • 支持MVCC

  • 为REPEATABLE级别

  • 使用一种被称为next-key locking的策略来避免幻读现象的产生。

  • 插入缓冲(insert buffer)、二次写
    (double write)、自适应哈希索引(adaptive,hash index)、预读(read ahead)等高性能和高可用

  • 聚集(clustered)的方式

  • 6字节的ROWID并以此作为主键

  • InnoDB存储引擎有多个内存块

    • 维护所有进程/线程需要访问的多个内部数据结构。
    • 缓存磁盘上的数据,方便快速地读取,同
      时在对磁盘文件的数据修改之前在这里缓存。
    • 重做日志(redo log)缓冲。
  • InnoDB存储引擎是多线程的模型
    - Master Thread是一个非常核心的后台线程,

  • Checkpoint的机制刷新回磁盘。

  • >SHOW VARIABLES
    LIKE’innodb_buffer_pool_size’\G;

  • 从InnoDB 1.0.x版本开始,允许有多个缓冲池
    实例。每个页根据哈希值平均分配到不同缓冲池
    实例中。这样做的好处是减少数据库内部的资源
    竞争,增加数据库的并发处理能力。可以通过参
    数innodb_buffer_pool_instances来进行配置,该值
    默认为1。

  • InnoDB存储引擎是怎么对这么大的内存区域进行
    管理的呢

    • LRU List、Free List和Flush List
    • 缓冲池中页的大小默认为16KB
    • 在InnoDB的存储引擎中,LRU列表中还加入了midpoint位置
    • 新读取到的页,虽然是最新访问的页,但并不是直接放入到LRU列表的首部,而是放入到LRU列表的midpoint位置。这个算法在InnoDB存储引擎下称为midpoint insertion strategy。在默认配置下,该位置在LRU列表长度的5/8处。midpoint位置可由参数innodb_old_blocks_pct控制
      • >SHOW VARIABLES
        LIKE’innodb_old_blocks_pct’\G;
    • innodb_old_blocks_pct默认值为37,表示新读取的
      页插入到LRU列表尾端的37%的位置(差不多3/8
      的位置)
    • midpoint之后的列表称为old列表,之前的列表称为new列表
    • 可以简单地理解为new列表中的页都是最为
      活跃的热点数据。
  • 那为什么不采用朴素的LRU算法,直接将读
    取的页放入到LRU列表的首部呢?

    • 因为若直接将读取到的页放入到LRU的首部,那么某些SQL操作可能会使缓冲池中的页被刷新出,从而影响缓冲池的效率
      • 常见的这类操作为索引或数据的扫描操作

        • 这类操作需要访问表中的许多页,甚至是全部的页,而这些页通常来说又仅在这次查询操作中需要,并不是活跃的热点数据。
        • 如果页被放入LRU列表的首部,那么非常可能将所需要的热点数据页从LRU列表中移除,而在下一次需要读取该页时,InnoDB存储引擎需要再次访问磁盘
        • 引入innodb_old_blocks_time,用于表示页读取到mid位置后需要等待多久才会被加入到LRU列表的热端
        • 因此当需要执行上述所说的SQL操作时,可以通过下面的方法尽可能使LRU列表中热点数据不被刷出
        mysql>SET GLOBAL
        innodb_old_blocks_time=1000;
        Query OK,0 rows affected(0.00 sec)
        #data or index scan operation
        ……
        mysql>SET GLOBAL innodb_old_blocks_time=0;
        Query OK,0 rows affected(0.00 sec)
        
        • 如果用户预估自己活跃的热点数据不止63%,那么在执行SQL语句前,还可以通过下面的语句来减少热点页可能被刷出的概率

               ```
            mysql>SET GLOBAL innodb_old_blocks_pct=20;
           Query OK,0 rows affected(0.00 sec)
          
              ```
          
  • Free列表

    • 但当数据库刚启动时,LRU列表是空

    • 这时页都存放在Free列表中。当需要从缓冲池中分页时,首先从Free列表中查找是否有可用的空闲页,若有则将该页从Free列表中删除,放入到LRU列表中。否则,根据LRU算法,淘汰LRU列表末尾的页,将该内存空间分配给新的页。

    • SHOW ENGINE INNODB STATUS

      • 来观察LRU列表及Free列表的使用情况和运行状态。

        mysql>SHOW ENGINE INNODB STATUS\G;
        ***************************1.row***************************
        Type:InnoDB
        Name:
        Status:
        =====================================
        120725 22:04:25 INNODB MONITOR OUTPUT
        =====================================
        Per second averages calculated from the last
        24 seconds
        ……
        Buffer pool size 327679
        Free buffers 0
        Database pages 307717
        Old database pages 113570
        Modified db pages 24673
        Pending reads 0
        Pending writes:LRU 0,flush list 0,single
        page 0
        Pages made young 6448526,not young 0
        48.75 youngs/s,0.00 non-youngs/s
        Pages read 5354420,created 239625,written
        3486063
        55.68 reads/s,81.74 creates/s,955.88
        writes/s
        Buffer pool hit rate 1000/1000,young-making
        rate 0/1000 not 0/1000
        
        
  • Buffer pool hit rate 表示缓冲池的命中率,通常该值不应该小于95%

  • 执行命令SHOW ENGINE INNODB STATUS显示的不是当前的状态,而是过去某个时间范围内InnoDB存储引擎的状态

  • 通过表INNODB_BUFFER_POOL_STATS来观察缓冲池的运行状态
    mysql>SELECT POOL_ID,HIT_RATE,
    ->PAGES_MADE_YOUNG,PAGES_NOT_MADE_YOUNG
    -FROM
    information_schema.INNODB_BUFFER_POOL_STATS\G;
    ***************************1.row***************************
    POOL_ID:0
    HIT_RATE:980
    PAGES_MADE_YOUNG:450
    PAGES_NOT_MADE_YOUNG:0
    
  • 还可以通过表INNODB_BUFFER_PAGE_LRU来观察每个LRU列表中每个页的具体信息,例如通过下面的语句可
    以看到缓冲池LRU列表中SPACE为1的表的页类型
    mysql>SELECT
    TABLE_NAME,SPACE,PAGE_NUMBER,PAGE_TYPE
    -FROM INNODB_BUFFER_PAGE_LRU WHERE
    SPACE=1;
    +------------+-------+-------------+--------
    -----------+
    |TABLE_NAME|SPACE|PAGE_NUMBER|PAGE_TYPE|
    +------------+-------+-------------+--------
    -----------+
    |NULL|1|0|FILE_SPACE_HEADER|
    |NULL|1|1|IBUF_BITMAP|
    |NULL|1|2|INODE|
    |test/t|1|3|INDEX|
    +------------+-------+-------------+--------
    -----------+
    4 rows in set(0.00 sec)
    
  • InnoDB存储引擎从1.0.x版本开始支持压缩页的功能,

    • 将原本16KB的页压缩为1KB、2KB、4KB和8KB

      • 而由于页的大小发生了变化,LRU列表也有了些许的改变。对于非16KB的页,是通过unzip_LRU列表进行管理的

      • 令SHOW ENGINE INNODB STATUS

      • mysql>SHOW ENGINE INNODB STATUS\G;
        ……
        Buffer pool hit rate 999/1000,young-making
        rate 0/1000 not 0/1000
        Pages read ahead 0.00/s,evicted without
        access 0.00/s,Random read ahead 0.00/s
        LRU len:1539,unzip_LRU len:156
        I/O sum[0]:cur[0],unzip sum[0]:cur[0]
        ……
        
        
  • Checkpoint技术

    • 当事务提交时,先写重做日志,再修改页。当由于发生宕机而导致数据丢失时,通过重做日志来完成数据的恢复。这也是事务ACID中D(Durability持久性)的要求。
    • 目的是解决以下几个问题:
      • 缩短数据库的恢复时间;
      • 缓冲池不够用时,将脏页刷新到磁盘;
      • 重做日志不可用时,刷新脏页。
    • Sharp Checkpoint
      • 发生在数据库关闭时将所有的脏页都刷新回磁盘,这是默认的工作方式,即参数innodb_fast_shutdown=1。
    • Fuzzy Checkpoint
      • 若数据库在运行时也使用SharpCheckpoint,那么数据库的可用性就会受到很大的影响
      • 故在InnoDB存储引擎内部使用FuzzyCheckpoint进行页的刷新,即只刷新一部分脏页,而不是刷新所有的脏页回磁盘
  • InnoDB存储引擎的关键特性包括

    • 插入缓冲(Insert Buffer)
      • InnoDB存储引擎开创性地设计了InsertBuffer,对于非聚集索引的插入或更新操作,不
        是每一次直接插入到索引页中,而是先判断插入的非聚集索引页是否在缓冲池中,若在,则直接插入;若不在,则先放入到一个Insert Buffer对象中,好似欺骗
      • 数据库这个非聚集的索引已经插到叶子节点,而实际并没有,只是存放在另一个
        位置。然后再以一定的频率和情况进行InsertBuffer和辅助索引页子节点的merge(合并)操作,这时通常能将多个插入合并到一个操作中(因为在一个索引页中),这就大大提高了对于非聚集索引插入的性能
      • Insert Buffer的使用需要同时满足以下两个条件:
        • 索引是辅助索引(secondary index);
        • 索引不是唯一(unique)的。
      • SHOW ENGINE INNODB STATUS来查看插入缓冲的信息
      • Insert Buffer存在一个问题是
        • 在写密集的情况下,插入缓冲会占用过多的缓冲池内存(innodb_buffer_pool),默认最大可以用到1/2的缓冲池内存。
          • 简单来说,修改IBUF_POOL_SIZE_PER_MAX_SIZE就可以对插入缓冲的大小进行控制。比如将IBUF_POOL_SIZE_PER_MAX_SIZE改为3,则最大只能使用1/3的缓冲池内存。
    • Change Buffer Insert Buffer的升级
      • InnoDB存储引擎可以对DML操作——INSERT、DELETE、UPDATE都进行缓冲,他们
        分别是:Insert Buffer、Delete Buffer、Purgebuffer
      • 适用的对象依然是非唯一的辅助索引。
      • UPDATE操作
        • 1、将记录标记为已删除; <---->Delete Buffer
        • 2、真正将记录删除。<---->Purgebuffer
      • innodb_change_buffering
        • inserts、deletes、purges、changes、all、none。inserts、deletes、purges
          • changes表示启用inserts和deletes
          • all表示启用所有
          • none表示都不启用。该参数默认值为all
        • innodb_change_buffer_max_size 来控制ChangeBuffer最大使用内存的数量:
          • innodb_change_buffer_max_size值默认为25,表示最多使用1/4的缓冲池内存空间。而需要注意的是,该参数的最大有效值为50。
    • 两次写(Double Write)
    • 自适应哈希索引(Adaptive Hash Index)
    • 异步IO(Async IO)
    • 刷新邻接页(Flush Neighbor Page)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值