InnoDB存储引擎 一
InnoDB基础架构
InnoDB存储引擎具有多个内存块,组成一个内存池。
内存池:
- 维护所以进程线程需要访问的多个内部数据结构
- 缓存磁盘文件数据,方便快速存取,同时对磁盘文件的数据修改之前在这里缓存
- 重做日志 redo log 缓冲
重要的后台线程
-
Master Thread
负责将数据异步刷新到磁盘,保证数据一致性 -
IO Thread
负责异步IO(AIO:Async IO)请求的回调。1.0版本的InnoDB共有4个IO:write,read,insert buffer,log IO Thread -
Purge Thread 清除/净化线程
用来回收已经使用并分配的undo页 -
Page Cleaner Thread
负责将脏页的刷新操作放到单独的线程中完成
内存
-
缓冲池
InnoDB是基于磁盘存储的,缓冲池的作用在于弥补CPU速度和磁盘速度之间的鸿沟。(类比操作系统的CACHE)
缓冲池中存储的页类型有:索引页,数据页,undo页,插入缓冲(insert buffer),自适应哈希索引(adaptive hash index),InnoDB存储的锁信息(lock info),数据字典信息(data dictionary)。其中最主要的是索引页和数据页。
- 缓冲池管理
-
LRU:
在InnoDB中,对LRU作了改进,最新读到的页并不直接放在队列首部,而是放在midpoint的位置,此算法称为midpoint insertion strategy。默认midpoint在LRU队列5/8处。在InnoDB中,把在midpoint之前的列表称为new列表,之后的列表称为old 列表,可以理解为new 列表是活跃的热点数据。
为了管理LRU列表,InnoDB还有一个参数innodb_old_blocks_time,用于表示把页读取到mid位置后还要等待多久才会被加入表头热端。 -
Free List
用于维持空闲页,LRU起初列表为空,申请时先看Free中有无空闲页,有则申请,无则淘汰LRU末尾页将其内存空间分配给新页。 -
Flush List
脏页:在对LRU列表中的页进行修改之后,该页称为“脏页”,即缓冲区和磁盘上的页数据不一致。数据库会通过checkpoint机制把脏页刷新回磁盘。
Flush列表中存储的页就是脏页。
-
重做日志缓冲
redo log buffer
独立于缓冲池的另外一个缓冲区,重做日志缓冲
每秒刷新
3种情况 发送刷新
1.Master thread 每一秒将重做日志缓冲刷新到重做日志文件
2.每个事务提交时会将重做日志刷新到重做日志文件
3.当重做日志缓冲池剩余容量小于1/2时,刷新 -
额外内存池
对数据结构本身(自身)存储的内存进行分配
比如缓冲池中的一些对象如帧缓冲对象,缓冲控制对象等,这些对象存储了LRU 、锁以及等待信息。但是这些对象的内存需要从额外内存池获取。
checkpoint技术
write ahead log
当事务提交时,先写重做日志,再修改页。防止当往磁盘刷写脏页时由于及其宕机造成数据不一致,数据丢失。保证ACID的D(durability 持久性)。
Sharp checkpoint:发生在数据库关闭时,将所有的脏页都刷新回磁盘,这是默认的工作方式。
Fuzzy checkpoint:InnoDB中会发生如下几种情况的Fuzzy checkpoint
- Master Thread checkpint
- FLUSH_LRU_LISTcheckpoint
- Async/Sync Flush checkpoint
- Dirty Page too much checkpoint
Master Thread的工作方式
InnoDB 1.0xx版本之前的Master Thread
首先明确在主线程中包括几个主要的循环
- loop 主循环
- background loop 后台
- flush loop
- suspend loop 挂起循环
Master Thread 的工作机制伪代码
void master_thread(){
goto loop;
loop:
for(int i=0;i<10;i++){
//循环内为每秒钟执行的动作,主循环中操作分两类:1.每秒 2.每十秒
thread_sleep(1)//sleep 1 second
do log buffer flush to disk; //每秒都做
if (last_one_second_ios<5)//如果前一秒的IO操作小于5次,那么就认为IO压力小,执行并行插入缓冲区
do merge at most 5 insert buffer
if (buf_get_modified_ratio_pct>innodb_max_dirty_pages_pct)
//innodb_max_dirty_pages_pct是系统设置的脏页比例 默认为90%
//如果缓冲池中脏页比例大于90%,则InnoDB存储引擎认为需要进行磁盘同步操作,将100个脏页写入磁盘
do buffer pool flush 100 dirty page
if (no user activity)
goto background loop
}
if(last_ten_second_ios<200)//此时跳出上面的for循环 表示下面是每10秒要进行的操作,此处是指如果过去10秒的io次数小于200,那么就磁盘刷写100页脏页
do buffer pool flush 100 dirty page
//下面这三个是每10秒都要无条件执行的
do merge at most 5 insert buffer
do log buffer flush to disk
do full purge//将无用的undo页删除
if(buf_get_modified_ratio_pct>70%)
do buffer pool flush 100 dirty page
else
do pool flush 10 dirty page
goto loop //继续第二个 为期11秒的循环(10+1)
background loop:
do full purge // 删除无用的undo页
do merge 20 insert buffer//合并插入20个缓冲区
if not idle://如果不空闲了 跳回主循环
goto loop
else:
goto flush loop
flush loop:
do buffer pool flush 100 dirty page
if (buf_get_modified_ratio_pct>innodb_max_dirty_pages_pct)
goto flush loop
goto suspend loop
suspend loop:
suspend_thread()
wating event
goto loop;
}
}