这里主要分析下InnoDB引擎相关。关于InnoDB和MyIsam引擎,官网说:除非需要用到某些InnoDB不具备的特性,并且没有其他办法可以替代,否则都应该选择InnoDB引擎。所以这里重点分析InnoDB。
InnoDB磁盘结构
整体来讲主要分为以下部分:系统表空间、用户表空间、redo 日志
- redo log:默认情况下,InnoDB储存引擎的数据目录下会有两个名为ib_logfile0和ib_logfile1的文件,这就是redo log file,记录了I对于InnoDB存储引擎的事务日志。它的作用是在Mysql数据储存出现问题时,能通过它将数据恢复为正确状态。 每个InnoDB引擎至少有一个重做日志组,每个组下最少有2个日志文件,比如默认的就是 ib_logfile0和ib_logfile1 ,每个文件默认大小50mb,同伙循环写入的方式运行,先写第一个文件,写满了就写第二个文件,当第二个也写满的时候就切换到第一个。可以通过 innodb_log_file_size 参数来设置redo log file 的大小。如果设置的太大在恢复的时候需要很长时间,如果太小会导致checkpoint的检查频繁刷新脏页到磁盘,对性能造成影响。
- 系统表空间:是被多个表共享的,对于磁盘上的 ibdata1 文件。
- 用户表空间:在对应的数据库目录下,有两个文件,一个是 表名.ibd,存的是具体的数据和索引;一个是表名.frm,存的是表结构。
- InooDB引擎数据储存的逻辑结构
表空间文件
表空间文件由多个段组成
段内部有多个区
区中包含多个页
页中包含多个行
行中保存数据库中的每一行数据 - InooDB引擎数据储存的物理结构
其中页是最小单位,每页大小16K,是磁盘和内存交互的最小单位;一个区由64个页组成,为了保证区中页的连续性,区扩展时会一次性从磁盘申请4~5个区。每次读取数据最小读取一页就是16K,和操作系统每次读取4K数据一个意思。
InnoDB内存结构
整体来讲内存结构主要分为以下部分:缓冲池(Buffer Pool)、修改缓冲区(Change Buffer)、自适应哈希索引、redo log Buffer、数据页、索引页、双写缓冲区等等…
- Buffer Pool
缓冲池的大小决定着数据库的整体性能,可以通过 innodb_buffer_pool_size 参数来设置。 - 数据页和索引页
- InnoDB存储引擎工作时,需要以Page页为最小单位去将磁盘中的数据加载到内存中,与数据 库相关的所有内容都存储在Page结构里。
Page分为几种类型,数据页和索引页就是其中最为重要的两种类型。 - 自适应哈希索引
InnoDB会根据访问的频率和模式,为热点页建立哈希索引,来提高查询效率。具体的比较复杂,这里不多细说。 - Redo Log Buffer
写数据的时候先把相关的变更信息写入到重做日志缓冲中,然后再按时或按事务提交时写入磁盘。
落盘过程
- 插入数据的时候,首先开启事务
- 写redo log buffer
- 写入到缓冲池中的数据页,这时形成脏页数据,脏页数据落盘是Checkpoint的时候才刷新回磁盘
- 事务提交触发redo log 落盘,这里落盘的机制分为三种情况,可以通过 innodb_flush_log_at_trx_commit 参数控制,默认是1
0:表示提交事务时只是将redo log buffer写入到操作系统的文件缓存,然后会按照每1秒的间隔调用操作系统的fsync函数刷新到磁盘。
1:表示事务提交的时候,将redo log buffer 中的数据写入操作系统的文件缓存,并且调用文件系统的fsync,这样确保数据真正的落盘成功。
2:表示事务提交的时候,只是将redo log buffer写入操作系统的文件缓存,但是不会调用fsync函数,而是由文件系统自己去判断何时落盘。
可以看得出来,每次提交事务都会把日志文件刷新到操作系统的缓冲区,只有设置为1是最安全但消耗性能的方式;0和2性能最好,但是在服务器意外宕机时会丢失1秒的数据。 - 事务提交成功,我们就可以任务数据已经保存了,如果此时脏页数据还没有落盘,只要有redo log,就可以从中恢复数据。
- 当发生了checkpoint时,就会对脏页数据落盘,只有脏页数据落盘了才是真正的持久化成功。脏页数据刷新回磁盘时采用的是双写过程,首先将脏页数据复制到内存中的双写缓冲区,然后通过双写缓冲区再分两次,每次1MB顺序写入共享表空间的物理磁盘上,然后调用fsync函数刷盘;然后再将脏页数据写入到各个用户表空间中。这样做是为了防止在将脏页数据落盘中发生了崩溃,可以从共享表空间中找到该页的副本。