Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  The InnoDB Storage Engine  /  InnoDB Multi-Versioning

17.3 InnoDB 多版本控制

InnoDB 是一个多版本存储引擎。它保留关于更改行的旧版本信息,以支持事务特性,如并发和回滚。这些建议信息存储在undo表空间中,称为回滚段。见第17.6.3.4节,“Undo Tablespaces”InnoDB 使用回滚段中的信息来执行事务回滚所需的undo操作,也用于构建一致读取时的行早期版本。见第17.7.2.3节,“Consistent Nonlocking Reads”

内部,InnoDB 对每个存储在数据库中的行添加三个字段:

  • 一个 6 字节的 DB_TRX_ID 字段表示最后一次插入或更新该行的事务标识符。同时,删除也被内部视为更新,其中一个特殊位在行中设置,以标记它为已删除。

  • 一个 7 字节的 DB_ROLL_PTR 字段称为回滚指针。回滚指针指向了写入到回滚段中的undo日志记录。如果该行被更新,undo日志记录包含必要信息,以重建该行在更新前时的内容。

  • 一个 6 字节的 DB_ROW_ID 字段包含一个行 ID,该 ID 在插入新行时递增。如果 InnoDB 自动生成聚簇索引,那么该索引包含行 ID 值。否则,DB_ROW_ID 列不出现在任何索引中。

回滚段中的undo日志被分为插入和更新undo日志。插入undo日志仅在事务回滚时需要,并且可以在事务提交后立即丢弃。更新undo日志也用于一致性读取,但只能在没有任何事务对其进行快照的同时丢弃。对于更多关于undo日志的信息,请见第17.6.6节,“Undo Logs”

建议您定期提交事务,包括只执行一致性读取的事务。否则,InnoDB无法丢弃更新undo日志中的数据,回滚段可能会增长太大,占用undo表空间的存储空间。在管理undo表空间方面,请见第17.6.3.4节,“Undo Tablespaces”

回滚段中的undo日志记录的物理大小通常小于相应插入或更新的行。您可以使用这个信息来计算回滚段所需的存储空间。

InnoDB多版本控制方案中,当使用SQL语句删除一个行时,InnoDB不会立即物理删除该行和其索引记录。InnoDB直到丢弃了对删除操作的更新undo日志记录后才会进行物理删除,这个删除操作称为purge,通常时间与执行删除语句相同。

如果您在表中插入和删除小批量数据,速度相似,purge线程可能会落后,表将不断增长,因为所有"dead"行,使得一切都变慢。 在这种情况下,可以通过调整innodb_max_purge_lag系统变量来限制新行操作的速度,并为purge线程分配更多资源。有关详细信息,请参阅第17.8.9节,“Purge Configuration”

Multi-Versioning and Secondary 索引

InnoDB多版本并发控制(MVCC)对次要索引的处理方式不同于聚簇索引。聚簇索引中的记录在原地更新,并且隐藏的系统列指向undo日志条目,从而可以重构早期记录版本。与聚簇索引记录不同,次要索引记录不包含隐藏的系统列,也不在原地更新。

当次要索引列被更新时,旧的次要索引记录将被删除标记,新记录将被插入,并且删除标记记录最终将被purge。 当次要索引记录被删除标记或次要索引页面由 newer事务更新时,InnoDB将在聚簇索引中查找数据库记录。在聚簇索引中,记录的DB_TRX_ID将被检查,并从undo日志中检索记录的正确版本,如果记录在读取事务启动后被修改。

如果一个辅助索引记录被标记为删除或辅助索引页面由 newer事务更新,覆盖索引技术将不被使用。相反,InnoDB 将从聚簇索引中查找记录。

然而,如果启用了索引条件下推优化,并且WHERE条件的一部分可以使用索引字段来评估,MySQL 服务器仍然将该部分WHERE条件推送到存储引擎中,以便使用索引进行评估。如果找不到匹配记录,则避免了聚簇索引查找。如果找到匹配记录,即使其中包含删除标记的记录,InnoDB 将从聚簇索引中查找记录。