跳至主要內容

InnoDB引擎

向往大约 5 分钟数据库Mysql

InnoDB引擎

InnoDB存储结构如下:

InnoDB_int

内存结构如下:

  • Buffer Pool:缓冲池是InnoDB在启动时分配的一个内存区域,用于InnoDB在访问数据时缓存表和索引数据。利用缓冲池,可以合并一些对经常访问的数据的操作,直接从内存中处理,加快了处理速度。通常,在专用数据库服务器上,可以将80%的物理内存分配给InnoDB缓冲池。
  • Adaptive Hash Index:自适应哈希索引,用于管理缓冲池中的内部数据结构,并对缓冲池中的相关工作负载和内存操作组合进行自动调节,且不会牺牲任何事务功能、性能和可靠性
  • Log Buffer(Redo Log Buffer):重做日志缓冲区是用于保存将要写入重做日志磁盘文件中的数据的内存缓冲区域。重做日志缓冲区的大小由innodb_log_buffer_size配置参数定义。重做日志缓冲区中的内容会定期刷新到磁盘上的日志文件中。更大的重做日志缓冲区允许运行更大的事务,这在一定程度上避免提交大事务之前需要将重做日志写入磁盘中。因此,如果在应用场景中经常有大事务,则可以考虑增大重做日志缓冲区以减少磁盘I/O操作。

磁盘结构如下:

  • System Tablespace:InnoDB系统表空间包含InnoDB数据字典(InnoDB相关对象的元数据)、Doublewrite Buffer、Change Buffer磁盘部分和Undo Logs,还包含在系统表空间中创建的任何表和索引数据。
  • Doublewrite Buffer:双写缓冲区是一个位于系统表空间的存储区域,InnoDB在进行刷脏操作时,在将脏数据写入数据文件中的正确位置之前先把脏页从InnoDB缓冲池写入双写缓冲区中。只有将脏页成功写入并落盘到ibdata1共享表空间中的双写缓冲区之后,InnoDB才能将脏页从缓冲池中写入数据文件中的正确位置。如果操作系统、存储子系统或mysqld进程在刷新脏页过程中发生崩溃,那么可能发生部分写(InnoDB默认的页大小为16KB,而文件系统默认的块大小为4KB,如果InnoDB的一个页在写入磁盘过程中发生异常,则可能导致数据页只写入了一部分到磁盘中),InnoDB在重新启动时的崩溃恢复期间从双写缓冲区中找到正确的页面副本进行覆盖恢复。虽然双写会导致脏页被两次写入磁盘中,但双写缓冲区不需要两倍的I/O开销或两倍的I/O操作。因为脏页在双写时是以一次1MB,作为一个大的顺序块被写入双写缓冲区中,并执行一次fsync()调用的。
  • Undo Logs:用于存放事务修改之前的旧数据(undo log记录了有关如何撤销事务对聚集索引记录的最新更改的信息),基于undo实现了MVCC和一致性非锁定读。
  • Redo Logs:重做日志是在崩溃恢复期间使用的基于磁盘的数据结构文件,用于恢复不完整提交事务写入的数据。在MySQL实例正常运行期间,重做日志对事务产生的数据变更部分进行编码并持久化到磁盘中(重做日志中的数据就是对受影响的行记录进行编码,利用这些编码数据把事务进行前滚的操作就叫作重做)。在默认情况下,重做日志在磁盘中创建一组名为ib_logfile0和ib_logfile1的文件。MySQL以循环滚动方式写入重做日志文件,并使用一个不断增加的LSN值表示重做日志的写入量,以及标记写入重做日志文件中的位置。根据WAL(Write-Ahead Logging,日志先行)原则,在提交事务时会先使用redo log持久化事务发生修改的部分数据

工作流程:

UPDATE test SET idx = 2 WHERE id=1为例:

  1. 到了InnoDB存储引擎这里,先判断id=10这行数据对应的页是否在缓冲池中,如果不在,则将id=10记录对应的页从datafile中读入InnoDB缓冲池中。
  2. 将idx修改之前的值和对应的主键、事务ID原来的信息写入Undo Tablespace的回滚段中。
  3. 更改缓存页中的数据,并将更新记录和新生成的LSN值(日志序列号)写入Log Buffer中,更新完之后在缓冲池中这个页就是脏页。
  4. 在提交事务时,根据innodb_flush_log_at_trx_commit的设置,用不同的方式将Log Buffer中的更新记录刷新到redo log中,然后写binlog(二进制日志文件),写完binlog就开始commit(这里的commit是指binlog的commit,就是同步到磁盘),binlog同步之后就把binlog文件名和position(binlog文件内的位置)也写到redo log中。然后在redo log中写入一个commit标记,那么此时就完成了这个事务的提交。接下来释放独占锁。
  5. 后台I/O线程根据需要择机将缓存中合适的脏页刷新到磁盘数据文件中。当然,在刷新脏页时要先拷贝一份到双写缓冲区中(如果开启了双写缓冲区功能的话),当双写缓冲区中的数据落盘之后,再从缓冲池中把脏页刷新到各个数据文件中。