-
索引
- 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;
- >SHOW VARIABLES
- 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) ```
-
- 因为若直接将读取到的页放入到LRU的首部,那么某些SQL操作可能会使缓冲池中的页被刷新出,从而影响缓冲池的效率
-
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的缓冲池内存。
- 在写密集的情况下,插入缓冲会占用过多的缓冲池内存(innodb_buffer_pool),默认最大可以用到1/2的缓冲池内存。
- InnoDB存储引擎开创性地设计了InsertBuffer,对于非聚集索引的插入或更新操作,不
- 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。
- inserts、deletes、purges、changes、all、none。inserts、deletes、purges
- InnoDB存储引擎可以对DML操作——INSERT、DELETE、UPDATE都进行缓冲,他们
- 两次写(Double Write)
- 自适应哈希索引(Adaptive Hash Index)
- 异步IO(Async IO)
- 刷新邻接页(Flush Neighbor Page)
- 插入缓冲(Insert Buffer)
Innodb
最新推荐文章于 2024-11-14 12:24:32 发布