Mysql体系结构和存储引擎
Mysql体系结构
InnoDB存储引擎
InnoDB通过使用MVCC来获取高并发性,并且实现了SQL标准的四种隔离级别,默认为RepeatedRead级别,同时使用了Next-key Lock的策略来避免幻读,除此之外还提供了插入换种,二次写,自适应哈希索引,预读等高性能和高可用的功能.
InnoDB对于数据存储采用了聚集的方式,没张表的存储都是按照主键的书序存放的,当没有指定主键时,InnoDB会为每行生成一个6字节的ROWID
MyISAM存储引擎
MyISAM不支持事务,是表锁设计,支持全文索引,在缓冲池只换存索引文件,而不缓存数据文件
InnoDB和MyISAM的比较
栏目 | InnoDB | MyISAM |
---|---|---|
事务 | 支持 | 不支持 |
锁 | 行锁 | 表锁 |
MVCC | 支持 | 不支持 |
索引B-Tree | 支持 | 支持 |
索引hash | 支持 | 不支持 |
聚集索引 | 是 | 不是 |
缓冲池是否缓存数据 | 是 | 只换存索引 |
外键 | 支持 | 不支持 |
InnoDB存储引擎
InnoDB体系架构
- 维护所有进程和县城需要访问的多个内部数据结构
- 缓存磁盘上的数据,方便快速读取
-
重做日志(redo)缓冲
后台线程主要负责刷新内存池中的数据,保证缓存池中的内存缓存是最近的数据,并将已修改的数据文件刷新到磁盘文件,
后台线程
Master Thread
是一个核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据一致性,包括脏页的刷新,合并插入缓冲,UNDO页回收等IO Thread
在InnoDB中使用了大量AIO来处理写请求,这样可以极大的提高数据库的性能,IO Thread的工作主要就是负责这些IO请求的回调处理Purge Thread
事务被提交后,所使用的undolog可能不在需要,因此PurgeThread来回头已经使用并分配undo页,
内存
缓冲池
InnoDB存储引擎是基于磁盘的,并将其记录按照页的方式进行管理,通过内存来弥补磁盘速度的不足
对于数据库中页的修改操作,首先修改在bufferpool中的页,然后再以一定的频率刷新到磁盘
缓存池中的数据页有: 索引页,数据页,undo页,插入缓冲页,自适应哈希索引,InnoDB存储的锁信息,数据字典信息等
LRU List, Free List和Flush List
1. LRU List
数据库中的缓冲池是通过LRU算法进行管理的,当缓冲池不能存放新读取到的页时,首先释放LRU列表中尾端的页.在InnoDB中,缓冲池页大小默认为16kb,同样使用LRU进行管理,不过进行了一些优化,新读取的页不是放在最前端而是放到5/8处
2. Free List
当数据库刚启动时,LRU列表没有任何的页,都存放在Free列表中,当需要从缓冲池分页时,首先从Free列表中取出空闲页,如果没有则淘汰LRU末尾的页
3. Flush List
当LRU列表的页被修改后,该页称之为脏页,即缓冲池数据与磁盘上的页的数据产生了不一致,这时数据库通过Checkpiont机制刷新回磁盘,而FlushList中的页即为脏页,但是也存在LRU列表中
重做日志缓冲(redo log buffer)
InnoDB除了有缓冲池外,也有重做日志缓冲,首先将重做日志放到这个缓冲区中,然后以一定频率刷新到重做日志文件,重做日志会在MasterThread,事务提交及剩余重做日志缓冲池小于1/2进行刷新
CheckPoint技术
为了避免数据因宕机丢失,数据库采用先写重做日志再修改缓冲池页的方式
优点
缩短数据库恢复时间
数据库宕机时,不用重新读取所有重做日志,以为checkpiont以前的页已经刷新到磁盘,只需要对checkpoint以后的页进行恢复缓冲池不够时,刷新到磁盘
如果缓冲池不够,回收的末尾页为脏页,则需要强制执行checkpoint重做日志不可用时,刷新脏页
Master Thread工作方式
Master具有最高的线程优先级,其内部由多个循环组成:主循环,后台循环,刷新循环机暂停循环
-
Loop循环
每1s:- 重做日志缓冲刷新到磁盘,即使这个事务还没有提交(总是)
- 合并5个插入缓冲(可能)
- 至多刷新100个buffer pool的脏页到磁盘(可能)
- 当前没有用户活动,切换到background loop(可能)
每10s:- 刷新100个脏页到磁盘(可能)
- 合并5个插入缓冲(总是)
- 重做日志缓冲刷新到磁盘,即使这个事务还没有提交(总是)
- 删除无用的undo也(总是)
- 刷新100个或10个脏页到磁盘(总是)
-
background loop循环
- 删除无用的undo页(总是)
- 合并20个插入缓冲(总是)
- 跳回到主循环(总是)
- 不断刷新100个页直到符合条件(可能,跳转到flush loop中完成)
InnoDB关键特性
插入缓冲
插入缓冲和数据页一样是物理页的一个组成部分,非唯一索引的辅助索引应用,b+树实现
其中对于非聚集索引的插入或更新操作并不是每一次直接插入到索引页中,
- 先判断插入的非聚集索引是否在缓冲池中,若在则直接插入;
- 若不在则先放到一个插入缓冲中,看似插入到非聚集索引的叶子节点,而实际并没有,只是放到另一个位置中,然后再以一定的频率从和情况进行插入缓冲和辅助索引叶子节点的merge操作,这样通常可以将多个插入合并到一个操作中,提升了非聚簇索引的插入性能
change buffer
视为插入缓冲的升级版,增加Delete Buffer和Purge Buffer
对一条记录进行update可以分为两个过程
- 将记录标记为删除(Delete Buffer)
- 真正将记录删除(Purge Buffer)
两次写 doublewrite
当发生数据库宕机时,innodb正在写入某个页到表中,但是这个页只写了一部分,在恢复时,应用重写日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副本还原该页,在进行重做日志恢复
doublewrite由两部分组成,一个内存中的doublewrite buffer,大小为2m,另一个为物理磁盘共享表空间中连续的128个页,即两个区.
在缓冲池脏页刷新到磁盘时,并不直接写磁盘,而是通过memcpy喊出拷贝到内存的双写缓冲区中,然后再分两次写入共享表空间的物理磁盘上,最后马上调用fsync函数,同步磁盘,避免缓冲写带来的问题
自适应哈希索引
innodb会自动根据访问频率和模式来自动地为某些热点页简历哈希索引