InnoDB存储引擎的版本
Mysql5.5 InnoDB1.1.X
Mysql5.6 InnoDB1.2X
InnoDb体系架构
后台线程
- Master线程:缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓冲、undo页的回收。
- IO线程:InnoDB存储引擎中大量使用AIO。IO线程主要工作是负责这些IO请求的回调
- Purge线程:回收已经使用并分配的undo页。InnoDb1.1开始引入。
- Page Cleaner Thread线程:脏页刷新操作。InnoDB1.2开始引入。
内存
缓冲池
一共八种,分为Mysql缓冲和InnoDB缓冲
·LRU List、Free List和FlushList
LRU:最近最久未使用,局部性原理。将页放到队首,查重。改进将选中页防止队列5/8处
LFU:基于次数。
优化点: - 设置midpoint;
- 设置命中页到达热端的命中次数;
- 设置热点页被刷出的概率;
- show engine innodb status; innodb_buffer_pool_stats表。查看LUR、FreeList、命中率 等内存使用信息
unzip_LRU:管理压缩后的页,页的默认大小为16KB
伙伴算法:(申请4KB页为例) - 检查4DB的unzip_LRU列表,减产是否与可用的空闲页
- 若有直接使用
- 否则,检查8KBunzip_LRU列表
- 若能够得到空闲页,将页分成2个4KB页,存放到4KB的unzip_LRU列表
- 如不能得到空闲页,将LRU列表申请一个16KB的页,将页分为1个8KB的页和2个4KB的页
Flush列表 保存脏页,同时脏页也保存在LRU列表中重做日志缓冲
InnoDB存储引擎首先将重做日志信息放入到这个缓冲区,然后按一定频率将其刷新到重做日志文件。
重做日志刷新到磁盘时机: - Master线程每一秒刷新一次
- 每个事务提交时会刷新
- 重做日志缓冲池空间小于1/2时
额外内存池
InnoDB中,对内存的管理通过一个称为内存堆的方式进行。在对一些数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当该区域的内存不够时,会从缓冲池中进行申请。CheckPoint技术
将脏页强制刷新到磁盘。解决问题: - 缩短数据库恢复时间
- 缓冲池不够用时,将脏页刷新到磁盘
- 重做日志不可用时,刷新脏页
InnoDB通过LSN来标志版本,LSN是8字节的数字。每个页有LSN,重做日志中也有LSN,Checkpoint也有LSN。
Sharp Checkpoint:
默认工作方式,数据库关闭时将所有脏页刷新到磁盘
Fuzzy Checkpoint:刷新时机 - 间隔一段 时间刷新
- 更新LRU列表刷新,被移除队列的页
- 重做日志文件不可用,循环使用重做日志文件。P35???
- 脏页太多 默认75页
Master 工作方式 P36
InnoDB 1.1
**磁盘操作会考虑IO的使用情况
每一秒的操作:
- 日志缓冲刷新到磁盘,即使这个事务还没有提交 (总是)
- 合并插入缓冲(可能)
- 至多刷新100个脏页到磁盘
- 没有用户活动切换到backgroud loop
没十秒的操作: - 刷新100个脏页到磁盘
- 合并至多5个插入缓冲(总是)
- 删除无用的Undo页(总是)
- 将日志缓冲刷新到磁盘(总是)
刷新100个或者10 个脏页到磁盘(总是)
backgroud loop 操作 没有用户活动或者关闭数据库 - 删除无用undo页
- 合并20个插入缓冲
- 跳回到主循环
InnoDB关键特性
插入缓冲
背景:辅助索引插入的值不是单调递增或者单调递减。
操作:对于非聚集索引的插入或者更新操作,不是每一次直接插入到索引页,而是先判断插入的非聚集索引页是否在缓冲池中,若在,则直接插入;若不在,则先放入到一个InsertBuffer对象中,好似欺骗。然后再以一定的频率和情况进行Insert Buffer和辅助索引叶子节点的mege操作。
使用范围:辅助索引,索引不是唯一的
Chage Buffer
Insert、Delete、Update都进行缓冲,可以设置启用或禁止其中的某项。
Insert Buffer的内部实现 P51
InsertBuffer 数据结构是一颗B+树。全局一个B+树,这颗B+树放在表空间中,默认是ibdata1中。
space 表示 表空间id
offerset 表示页所在的偏移量
metadata 排序呢每个记录进入InsertBuffer的顺序
Insert Buffer BitMap 用来标记每个辅助索引页的可用空间。
两次写
重做日志中记录的是对页的物理操作,如偏移量800写‘aaaa’记录。如果这个页本身已经发生了损坏,在对其进行重做是没有意义的。这就是说,在应用重做日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是doublewrite。
doublewrite由两部分组成,一部分是内存中doublewrite buffer,大小为2MB,另一部分是物理磁盘上共享表空间中连续的128个页,即两个区,大小同样为2MB。在对缓冲池的脏页进行刷新时,通过memcpy函数将脏页先复制到内存doublewrite buffer,之后分两次,每次1MB顺序写入共享表空间的磁盘上,然后调用fsync函数,同步磁盘,避免缓冲写带来的问题。
自适应哈希索引
访问模式一样。以该模式访问100次,页通过该模式放了N次,页中记录/16.
异步IO
刷新临近页
启动、关闭和恢复
SQL
- show engine innodb status; 查看innodb的状态信息
- show variables like ‘%version%’;可以查看mysql和innodb的版本信息
- innodb_file_io_thread 设置IO线程数量 innodb_read_io_thread;innodb_write_io_thread
- innodb_purge_threads 设置purge线程数量
- innodb_buffer_pool_size;缓冲池大小
- innndb_buffer_pool_instances;InnoDB缓冲池数量;
- 数据表innodb_buffer_pool_stats保存innoDB相关信息
- innodb_old_blocks_time 页读取到mid位置后需要等待多久才会被加入到LRU的热端
- innodb_buffer_page_lru表 查看LUR列表的信息
- innodb_log_buffer_size 重做
- innodb_lru_scan_depth LRU队列中可用页数量
- innodb_lru_scan_depth LRU队列中空闲页的最小数值 默认1024
- innodb_max_dirty_pages_pct 最大脏页数量,否则刷新会磁盘