一、介绍
1、所看书籍《Mysql技术内幕》
2、操作数据库版本8.0
3、innoDb是一个高性能、高可用、高扩展的存储引擎。
二、:InnoDB内存池负责
描述:InnoDB存储引擎有多个内存块,可以认为这些内存块组成了一个大的内存池负责:
1、维护所有进程/线程需要访问的对歌内部数据结构
2、缓存磁盘上的数据,方便快速地读取,同时在对磁盘文件的数据修改之前在这里缓存
3、重做日志(redo log)缓冲
4、后台线程的主要作用是负责刷新内训池中的数据,保证缓冲池中的内存缓冲的是最近的诗句。将已经修改的数据刷新到磁盘文件,保证在数据库发生异常的情况下innodb能恢复带正常运行状态。
三、后台线程讲解
1、InnoDB存储引擎是多线程的模型,因此其后台有多个不同的后台线程,负责处理不同的任务。
2、Master Thread 是一个非常核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓冲(INSERT BUFFER)、UNDO页的回收。
3、IO Thread:在InnoDB 存储引擎中大量使用了AIO(Async IO)来处理写IO请求,这样可以极大提高数据库的性能。IO Thread的工作主要是负责这些IO 请求的回调(call back)
1)InnoDB1.0版本之前共有4个IOThread : write 、read、insert buffer 、log IOthread
2) 1.x开始read thread 和 write thread 分别增大到了4个。
3) 分别使用innidb_read_io_thread 和innidb_write_io_thread参数进行设置
show VARIABLES like ‘INNODB_version’
show VARIABLES like ‘INNODB_%io_threads’
show ENGINE INNODB STATUS 观察InnoDB中的IO Thread
4)IO Thread 0 : insert buffer thread
5)IO Thread 1: log thread
6)读线程的ID总是小于写线程
4、Purge Thread :事务被提交后,其所使用的undolog可能不在需要,因此需要PurgeThread来回收已经使用并分配的undo页。目的减轻Master Thread的工作,提高CPU的使用率以及提升村粗引擎的性能。可以配置innodb_purge_thread参数
SELECT VERSION()
show VARIABLES like ‘INNODB_purge_threads’
四、内存讲解
1、缓冲池
1)InnoDB 存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。
2)可视为基于磁盘的数据库系统(Disk-base Database)
3)基于磁盘的数据库系统通常使用缓冲池技术来提高数据库的整体性能
4)缓冲池:一块内存区域 => 通过内存的速度来弥补磁盘速度较慢对数据库性能的影响。
5)数据库读取页=> 磁盘读取到的页 存放在缓冲池中(将页FIX在缓冲池)=> 下一次读相同的页 => 判断是否在缓冲池中 => 命中缓冲池 直接读取缓冲 返回 => 否则读取磁盘上的页。
6)数据更新 =>Checkpoint机制刷新回磁盘 (首先修改在缓冲池中的页 => 在以一定的频率刷新到磁盘上)
show VARIABLES like’innodb_buffer_pool_size’
7)缓冲池中的数据页类型有:索引页、数据页、undo页、插入缓冲(insert buffer)、自适应哈希索引(adaptive hash index)、InnoDB存储的锁信息(lock info)、数据字典信息(data dictionary)等
8)InnoDB1.x版本开始,允许有多个缓冲池实例。每个页根据哈希值平均分配到不同缓冲池实例中。目的:减少数据库内部资源竞争,增加数据库的并发处理能力 可以通过innodb_buffer_pool_instances配置
SHOW VARIABLES LIKE ‘innodb_buffer_pool_instances’ 默认一个
9)配置后可以通过
show engine innodb status 查看详细信息
select pool_id,pool_size,free_buffer,database_pages from innodb_buffer_pool_stats
2、LRU List、Free List 和 Flush List
1)数据库中的缓冲池是通过LRU(Lastes Recent Uesd,最近最少使用)算法来进行管理的。最频繁使用的页在LRU列表的前端,而最少使用的页在LRU 列表的尾端。
缓冲池不能存放新的读取页 => 释放LRU列表中尾端的页
2)Innodb缓冲池中页的大小默认为16kb 也使用LRU算法对缓冲池进行管理。但是做了一些优化
3)在innodb的存储引擎中LRU列表中还加入了midpoint位置。
新读取到的页 => 加入到LRU 列表的midpoint位置, 是innodb的一种策略midpoint insertion strategy ,默认位置在LRU列表长度的5/8处。midpoint位置可由参数innodb_old_blocks_pct控制
SHOW VARIABLES LIKE ‘innodb_old_blocks_pct’
4)为什么不放在首部:防止某些sql操作可能会使缓冲池中的页被刷新出,从而影响缓冲池的效率。常见的操作为索引、数据的扫描操作。这种操作需要访问表中的许多页,甚至是全部的页。如果这次查询的不是活跃的热点数据,而是一次简单的操作。那么放在列表首部可能将热点数据页从LRU列表中移除,下次读取被刷新出的页时就需要再次访问磁盘。
为了解决这个问题:innodb存储引擎引入了另一个参数来进行管理LRU列表innodb_old_blocks_time,用于表示页读取到mid位置后需要等多久才会被加入到列表的热端
根据实际情况合理的设置自己需要的东西
set GLOBAL innodb_old_blocks_time=1000;
set GLOBAL innodb_old_blocks_time=0;
set GLOBAL innodb_old_blocks_pct=20;
5)show engine innodb status 是过去某个时间范围内innodb存储引擎的状态

3、unzip_LRU是则样从缓冲池中分配内存呢?
1)检查4kb的unzip_LRU列表,检查是否有可用的空闲页
2)若有,则直接使用
3)否则,检查8kb的unzip_LRU列表
4)若能够得到空闲页,将页分成2个4kb,存放到4kb的unzip_LRU列表
5)若不能得到空闲页,从LRU列表中申请一个16kb的页,将页分为1个8kb的页、2个4kb的页,分别存放到对应的unzip_LRU列表中。
6)查看脏页及他们对应的表和页的类型。此表在 information_schema
SELECT TABLE_NAME,space,page_number,page_type FROM INNODB_BUFFER_PAGE_LRU WHERE OLDEST_MODIFICATION >0
4、重做日志缓冲
1)InnoDB存储引擎的内存区域除了有缓冲池外,还有重做日志缓冲(redo log buffer)。Innodb存储引擎首先将重做日志信息放到这个缓冲去,然后按一定频率将其刷新到重做日志文件。
2)重做日志缓冲一般不需要设置得很大,因为一般情况下每一秒钟将会重做日志缓冲刷新到日志文件。
3)用户只需要保证每秒产生的事务量在这个缓冲大小之内即可。
4)可以配置参数innodb_log_buffer_size控制,默认为8mb
show VARIABLES like’innodb_log_buffer_size’
5)三种会将重做日志缓冲中的内容刷新到外部磁盘的重做日志文件中
a:Master Thread 每一秒将重做日志缓冲刷新到重做日志文件
b:每个事务提交时会将重做日志缓冲刷新到重做日志文件
C:当重做日志缓冲池剩余空间小雨1/2时,重做日志缓冲刷新到重做日志文件。
5、额外的内存
1)在innodb存储引擎中,对内存的管理是通过一种称为内存堆(heap)的方式进行的。在对数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当该区域的内存不够时,会从缓冲池中进行申请。
2)在申请了很大的InnoDB缓冲池时,也应考虑相应的增加这个值。