笔记整理自:黑马MySQL数据库InnoDB存储引擎教程,详解InnoDB引擎架构及原理
Mysql5.5版本开始,默认使用InnoDB存储引擎,它擅长事务处理,具有崩溃恢复特性,在日常开发中使用非常广泛。
InnoDB逻辑存储结构
一个区的大小是1MB,一个页是16KB, 一个区包含64个连续的页。
InnoDB引擎在分配空间的时候,会一次性申请4到5个区,从而保证申请到的页是连续的。
InnoDB的内存结构(左)及磁盘结构(右)
InnoDB内存结构
1. Buffer Pool缓冲区
Mysql服务80%的内存会分配给缓冲区,以提高Mysql的并发访问性能。
2. Change Buffer写缓冲区
3. 自适应hash索引
4. 日志缓冲区
InnoDB磁盘结构
磁盘结构包括:系统表空间,独立表空间,通用表空间,撤销表空间,临时表空间,双写缓冲器,重做日志。
后台线程
进行内存与磁盘的通信。用于将内存结构中的数据刷新到磁盘结构。
后台线程包括四类线程:Master Thread, IO Thread,Purge Thread, Page Cleaner Thread
事务原理
事务时一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
ACID特性
原子性(Atomicity)
事务是不可分割的最小操作单元,要么全部成功,要么全部失败。undo log保证原子性。
一致性(Consistency)
事务完成时,必须使所有的数据都保持一致状态。由原子性和持久性一起保证一致性。
隔离性(Isolation)
数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。锁和MVCC保证隔离性。
持久性(Durability)
事务一旦提交或回滚,它对数据库中的数据的改变是永久的。redo log保证持久性。
redo.log
WAL(Write-Ahead Logging) 先写日志: DML语句执行之后,把对数据的修改记录在Buffer Pool的页中,此时叫做脏页(缓冲池的数据页有修改,但磁盘中没有同步更新)。然后将数据页的变化记录到redo log buffer中。事务commit之后,将内存的redo log buffer刷新到磁盘的redo log file中。一段时间后,如果脏页刷新到磁盘时出错了,可以根据redo log进行回滚,因为redo log记录了当次数据的变化。
脏页的数据并不是实时刷新的,而是一段时间之后通过后台线程将脏页数据刷新到磁盘。脏页成功刷新到磁盘后,会清理掉redo log,它是循环利用的。
如果每次执行了DML,都实时将脏页数据刷新到磁盘,会造成大量的随机I/O,性能下降。redo log是在日志后追加,是顺序I/O,速度更快。
undo log
MVCC
MVCC(Muitl-Version Concurrency Control),多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐藏字段,undo log日志, ReadView。
当前读
读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加索。对我们日常的操作,如:select … lock in share mode(共享锁),select … for update,update,insert,delete(排他锁)都是一种当前读。
快照读
简单的select(不加锁)就是快照读,读取的时记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。
- Read Commited:每次select,都生成一个快照读。
- Repeatable Read:开启事务后,第一个select语句才是快照读的地方。
- Serializable:快照读会退化为当前读。
记录的隐藏字段
undo log
回滚日志,在insert,update,delete的时候产生的便于数据回滚的日志。
当insert的时候,产生的undo log日志只在回滚时需要,在事务提交之后,可被立即删除。
而update,delete的时候,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会立即被删除。
undo log版本链
ReadView