本文整理自网络,侵删。
前言
在MySQL中InnoDB属于存储引擎层,并以插件的形式集成在数据库中。从MySQL5.5.8开始,InnoDB成为其默认的存储引擎。InnoDB存储引擎支持事务、其设计目标主要是面向OLTP的应用,主要特点有:支持事务、行锁设计支持高并发、外键支持、自动崩溃恢复、聚簇索引的方式组织表结构等。
体系架构
InnoDB存储引擎是由内存池、后台线程、磁盘存储三大部分组成。
线程
InnoDB 使用的是多线程模型, 其后台有多个不同的线程负责处理不同的任务
Master Thread
Master Thread是最核心的一个后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性。包括脏页刷新、合并插入缓冲、UNDO页的回收等。
IO Thread
在 InnoDB 存储引擎中大量使用了异步IO(Async IO)来处理写IO请求, IO Thread的工作主要是负责这些 IO 请求的回调。
Purge Thread
事务提交后,其所使用的undo log可能不再需要,因此需要Purge Thread来回收已经分配并使用的UNDO页。InnoDB支持多个Purge Thread, 这样做可以加快UNDO页的回收,提高CPU的使用率以及提升存储引擎的性能。
Page Cleaner Thread
Page Cleaner Thread的作用是取代Master Thread中脏页刷新的操作,其目的是减轻原Master Thread的工作及对于用户查询线程的阻塞,进一步提高InnoDB存储引擎的性能。
内存
InnoDB 存储引擎内存的结构
缓冲池
InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。但是由于CPU速度和磁盘速度之间的鸿沟,基于磁盘的数据库系统通常使用缓冲池记录来提高数据库的的整体性能。
缓冲池其实就是通过内存的速度来弥补磁盘速度较慢对数据库性能的影响。在数据库进行读取操作时,首先将磁盘中的页放入缓冲池中,下次再读取相同页时,首先从缓冲池中获取该页数据,起到高速缓存的作用。
数据的修改操作,则首先修改在缓冲池中的页数据,然后使用一种称为Checkpoint的机制刷新到磁盘上。
缓冲池的大小直接影响数据库的整体性能,对于InnoDB存储引擎而言,缓冲池配置通过参数 innodb_buffer_pool_size 来设置。使用 SHOW VARIABLES LIKE 'innodb_buffer_pool_size' 命令可查看缓冲池配置:
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size' \G *************************** 1. row *************************** Variable_name: innodb_buffer_pool_size Value: 134217728 1 row in set (0.01 sec)
缓冲池中缓存的数据页类型有: 索引页、undo页、插入缓冲、自适应哈希索引、InnoDB锁信息、数据字典信息等,索引页和数据页占缓冲池很大的一部分。
重做日志缓冲
缓冲池中的页数据比磁盘要新时,需要将新数据刷新到磁盘中。InnoDB采用Write Ahead Log策略来刷新数据,即当事务提交时,先写入重做日志缓冲,重做日志缓冲会按一定频率刷新到重置日志文件中,然后脏页会根据checkpoint机制刷新到磁盘。
重做日志缓冲不需要设置很大,通常情况下8M能满足大部分的应用场景。重做日志支持一下三种情况触发刷新:
- Master Thread每一秒将重做日志缓冲刷新到重做日志文件
- 每次事务提交时将重做日志缓冲刷新到重做日志文件
- 当重做日志缓冲池剩余空间小于1/2时,重做日志缓冲刷新到重做日志文件
额外内存池
在InnoDB存储引擎中,对内存的管理是通过一种称为内存堆的方式进行的。在对一些数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当该区域的内存不够时,会从缓冲池中进行申请。
锁
InnoDB支持的锁有:
- 共享锁和排它锁
- 意向锁
- 记录锁
- 间隙锁
- 自增锁
共享锁和排他锁
InnoDB引擎实现了两种标准的行级锁,共享锁(shared (S) locks) 和排他锁 (exclusive (X) locks)。共享锁允许一个占有锁的事务去读取一行数据,排它锁则允许事务对某一行记录进行写操作。
如果一个事务持有了一个共享锁,其他事务仍然可以获取这行记录的共享锁,但不能获取到这行记录的排它锁。当一个事务获取到了某一行的排它锁,则其他事务将无法再获取这行记录的共享锁和排它锁。
意向锁
在InnoDB中,意向锁是一种表级锁,分为共享锁和排他锁:
- 意向共享锁:将要去获取某一行的共享锁
- 意向排它锁:将要去获取某一行的排它锁
事务在获取共享/排它锁之前必须先获取意向共享/排它锁,意向锁不会阻塞其他任何对表的操作,他只是告诉其他事务他将要去获取某一行的共享锁或者排他锁。
记录锁
记录是是作用在索引上的一种锁,他锁住的是某一条记录的索引而非记录本身,如果当前表没有索引那么InnoDB将会为其创建一个隐藏的聚集索引,而Record Locks将会锁住这个隐藏的聚集索引。
间隙锁
间隙锁和记录锁一样也是作用在索引上,不同的是记录锁只作用于一条索引记录而间隙锁可以锁住一个范围内的索引。间隙锁在InnoDB的唯一作用就是防止其他事务的插入操作,以此防止幻读的发生。
自增锁
自增锁是一种特殊的表级锁,他只作用在包含自增列的插入操作时。当一个事务正在插入一条数据时,其他的任何事务都必须等待整个事务完成插入操作,在取获取锁来执行插入操作。
事务
ACID
事务是数据库作为OLTP最为重要的特性,说起事务不得不提起ACID四个基本特性:
- 原子性(Atomicity) :事务最小工作单元,要么全成功,要么全失败
- 一致性(Consistency): 事务开始和结束后,数据库的完整性不会被破坏
- 隔离性(Isolation) :不同事务之间互不影响,四种隔离级别为RU(读未提交)、RC(读已提交)、RR(可重复读)、SERIALIZABLE (串行化)
- 持久性(Durability) :事务提交后,对数据的修改是永久性的,即使系统故障也不会丢失
InnoDB的原子性、持久性和一致性主要是通过Redo Log、Undo Log和Force Log at Commit机制机制来完成的。Redo Log用于在崩溃时恢复数据,Undo Log用于对事务的影响进行撤销,也可以用于多版本控制。而Force Log at Commit机制保证事务提交后Redo Log日志都已经持久化。隔离性则是由锁和MVCC来保证的。
隔离级别
相关阅读 >>
更多相关阅读请进入《mysql》频道 >>

数据库系统概念 第6版
本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。