主要介绍MySql的整体体系结构和存储引擎
体系结构
概念上数据库是文件的集合,是按照一定的文件模型组织起来存放数据的结构;数据库实列是程序是一个用户进程,是用户对数据库进行操作的软件.
MySql主要由以下几部分组成
- 连接池组件
- 管理服务和工具组件
- SQL接口组件
- 查询分析器组件
- 优化器组件
- 缓冲组件
- 插件式存储引擎(存储引擎是基于表的 ,而不是基于数据库的)
- 物理文件
存储引擎
-
概述
存储引擎是与MySql物理文件进行交互的一种插件,存储引擎的底部是物理存储层,包括二进制日志文件,数据文件,错误文件,慢查询日志,undo/redo日志等 -
select的过程
下图是一次select的过程
从图中得知存储引擎位于是物理文件和程序数据之间
- InnoDB的体系架构
- 实列层
实列层主要包括’线程’和’内存’两个部分
a. 后台线程主要有
- Master Thread
主线程主要负责将缓冲池中的数据异步刷新到磁盘中,保证数据的一致性,包括脏页的刷新,合并插入缓冲等操作 - I/O Thread
I/O Thread 主要是负责AIO(Async IO)请求的回调 - Purge Thread
Purge Thread的作用是事物在被提交后undolog就可能不在被使用了,因此需要Purge Thread线程来回收并分配的undo页 - Page Cleaner Thread
Page Cleaner Thread的作用是回收分配脏页
小结:Master Thread和I/O Thread一个负责异步刷新数据一个负责AIO的回调,Purge Thread和Page Cleaner Thread一个负责回收分配undolog一个负责回收分配脏页
b. 内存
- 缓冲池
InnoDB存储引擎是基于磁盘存储,其中的数据是按照页的方式进行管理.由于CPU和磁盘速度中的差异因此用缓冲池技术来提高数据库的整体性能
缓冲池是一块内存区域,在数据库进行读取页操作时,会首先将从内存中的数据放到缓冲池中,在下一次读取相同页时,会直接读取缓冲池中的页数据.
对于数据库中的页的修改,首先会修改缓冲池中的页,然后以一定的频率刷新到磁盘,这种机制被称为CheckPoint
缓冲池中的数据页类型分为:
- 索引页
- 数据页
- undo页
- 插入缓冲
- 自适应哈希索引
- InnoDB存储的锁信息
- 数据字典
缓冲池存在的基础是因为关系型数据库的数据访问模式是遵循局部性原理,即单位时间内只会访问部分数据,因此可以使用缓冲池来提高数据的访问速度;
-
LRU list,Freen lst,Flush list
数据库中的缓冲池是通过LRU算法来进行管理,但是InnoDB中的LRU算法是经过优化的,将新数据放到列表3/8处;其中Buffer pool hit rate是一个非常重要的指标,标识数据从缓冲池中读取数据的命中率,如果太低说明缓冲池不够大或者数据访问模式不符合局部性原理,通常为95%以上; -
重做日志缓冲
重做日志首先会放到缓冲区,然后按照一定的频率刷新到日志文件上,有三种情况会刷新重做日志:
1.Master Thread每一秒都会将日志缓冲刷新到日志文件;
2.每个事务提交时都会将重做日志刷新到文件
3.当重做日志缓冲池剩余空间小于1/2时,会将日志刷新到文件上 -
额外的内存池
额外的内存池作为缓冲池的备用,但缓冲池不够的时候,就会从额外的内存池中申请 -
Checkpoint技术
Mysql中数据的持久性是通过Write Ahead Log策略来保证,也就是先写日志文件,在修改数据文件.当宕机导致数据丢失时,会通过重做日志来进行数据恢复.
如果重做日志太大会导致数据恢复的很慢,因此mysql使用CheckPoint的技术来保证,CheckPoint是将缓冲池中的内存页刷新到磁盘的动作
Master Thread
Master Thread具有最高级别的线程优先级,内部有多个循环组成:主循环,后台循环,刷新循环,暂停循环.
Master Thread主要分为1s执行一次的操作:
- 日志缓冲刷新到磁盘,即使这个事务还没提交
- 合并插入缓冲
- 最多刷新100个InnoDB的缓冲池中的脏页到磁盘
- 如果当前没有用户活动,就切换到backgroud loop
10s执行一次的操作: - 刷新100个脏页到磁盘
- 合并至多5个插入缓冲
- 将日志缓冲刷新到磁盘
- 删除无用的Undo页
- 刷新100个或者10个脏页
InnoDB特点
- 插入缓冲(Insert Buffer)
- 两次写(Double Write)
- 自适应哈希索引(Adaptive Hash Index)
- 异步IO(Async IO)
- 刷新邻接页(Flush Neighbor Page)
插入缓冲
- Insert Buffer
Insert Buffer是在插入数据时将辅助索引先放到Insert Buffer中,然后在按照一定的频率将Insert Buffer中的数据和辅助索引页的子节点进行合并,这样能够提高非聚集索引的插入性能 - Change Buffer
Change Buffer作为Insert Buffer的升级,会将所有对非聚集索引的操作进行缓冲 - Insert Buffer的内部结构
Insert Buffer的数据结构是B+树,在Mysql4.1之前每张表都有一颗B+树;在现在的版本中全局只有一颗B+树,负责对所有表的辅助索引进行Insert Buffer,默认为ibdata1
Insert Buffer的非叶子节点是由space(待插入记录表的表空间id),offer(偏移量)构成;叶子节点是由space,offer,metadata(操作辅助索引的元数据-顺序,标识,类型) - merge Insert Buffer的过程
在三种情况下,MySql会将Insert Buffer刷新到辅助索引文件中,并且虽然Insert Buffer是有序的,但是在刷新时,是随机选取Insert Buffer中的一个页进行刷新,做这个的目的是为了保证公平性而舍弃顺序性.以下的三种情况会进行Inser Buffer的刷新 - 辅助索引页被读取到缓冲池中
- Insert Buffer BitMap记录Insert Buffer可用空间不足时
- Master Thread线程对Insert Buffer的刷新
两次写
两次写指的是当在直接写入某页时发生宕机,会有丢失数据的风险.通过向将脏页的数据转移到内存中的doublewrite buffer中,在将doublewrite中的数据同步写到共享表空间的物理磁盘文件上,第二次才将doublewrite buffer中的文件刷新到数据文件(.ibd)中,这样可以尽量保证数据文件的完整性
为什么需要使用redolog和doublewrite buffer同时来保证数据的完整性呢?
因为redolog是一种物理+逻辑相结合的方式的数据结构,在宕机时,redolog在设计上是为了保证事务的完整性,在故障恢复时不能处理页断裂的场景,对于页断裂的场景需要使用doublewrite buffer来进行恢复,后续事务的完整性还是通过redolog来保证的;并不是是同一页上既要使用redolog又要使用doublewrite buffer来进行恢复;
自适应哈希索引
自适应哈希索引指的是连续对热点数据的多次查询后会根据B+树索引生成对应的哈希索引,加快查询性能
异步IO
异步IO可以提高操作磁盘的效率,…
刷新邻接页
刷新邻接页指的是对脏页所在区的页进行检测,发现是脏页一并进行刷新
-
LRU列表 (Least Recently Used List)
用途: LRU列表主要用于管理缓冲池(Buffer Pool)中的页面。缓冲池是InnoDB用来缓存表数据和索引数据的主要内存区域 -
缓冲池 (Buffer Pool)
定义: 缓冲池是InnoDB存储引擎用来缓存表数据和索引数据的主要内存区域。它用于减少磁盘I/O操作,提高数据库的读写性能。
内容:
干净页 (Clean Pages): 这些页面是最近从磁盘加载到内存中的,并且自加载以来没有被修改过。
脏页 (Dirty Pages): 这些页面是已经被修改但尚未写回到磁盘的页面。 -
Flush列表
用途: Flush列表用于管理脏页(即已经被修改但尚未写入磁盘的页面)。它跟踪哪些页面需要刷新到磁盘 -
脏页 (Dirty Pages)
定义: 脏页是指在缓冲池中已经被修改但还没有同步到磁盘的数据页。这些页面需要通过后台线程定期刷新回磁盘以确保数据的一致性和持久性。
内容:
脏页是缓冲池的一部分,只是这些页面的状态标记为“脏”(即已修改)。
脏页的数据在刷新到磁盘之前,仍然保留在缓冲池中,可以继续被访问和修改。