learn_note/数据库/Mysql/Mysql-InnoDB/Multi-Versioning.md

3.7 KiB
Raw Blame History

Multi-Versioning 多版本控制

InnoDB 是一个多版本的存储引擎。 它保留有关已更改行的旧版本的信息,以支持并发和回滚等事务功能。

此信息存储在称为回滚段的数据结构中的撤消表空间中。请参阅第 15.6.3.4 节,“撤消表空间

InnoDB 使用回滚段中的信息来执行事务回滚中所需的撤消操作。

它还使用该信息来构建行的早期版本以实现一致读取。 请参阅第 15.7.2.3 节,“一致的非锁定读取”。

在内部InnoDB 向存储在数据库中的每一行添加三个字段

  • 一个 6 字节的 DB_TRX_ID 字段指示插入或更新该行的最后一个事务的事务标识符。 此外,删除在内部被视为更新,其中行中的特殊位被设置为将其标记为已删除。

  • 一个 7 字节的 DB_ROLL_PTR 字段称为滚动指针。 回滚指针指向一条写入回滚段的撤销日志记录。 如果该行已更新,则撤消日志记录包含在更新之前重建该行内容所需的信息。

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

回滚段

回滚段中的undo logs分为insert undo logsupdate undo logs

称为插入撤消日志和更新撤消日志

Insert undo logs只在事务回滚时需要一旦事务提交就可以丢弃。

update undo logs也用于一致性读取但只有在不存在 InnoDB 为其分配快照的事务后才能丢弃它们,在一致读取中可能需要更新撤消日志中的信息来构建早期版本的 数据库行。

建议您定期提交事务,包括仅发出一致读取的事务。 否则InnoDB 无法丢弃更新撤消日志中的数据,回滚段可能会变得太大,填满它所在的撤消表空间。有关管理撤消表空间的信息,请参阅第 15.6.3.4 节,“撤消表空间”。

在 InnoDB 多版本方案中,当您使用 SQL 语句删除行时,它不会立即从数据库中物理删除。 InnoDB在丢弃为删除而写的update undo log记录时只是在物理上删除对应的行及其索引记录。 这种删除操作称为清除,速度非常快,通常与执行删除的 SQL 语句所用的时间顺序相同。

如果您以几乎相同的速率在表中插入和删除行,清除线程可能会开始滞后,并且由于所有“死”行,表会变得越来越大,从而使所有内容都受磁盘限制并且非常 减缓。 在这种情况下,通过调整 innodb_max_purge_lag 系统变量来限制新行操作,并为清除线程分配更多资源。 有关详细信息,请参阅第 15.8.9 节,“清除配置”。

MVCC

多版本和二级索引 InnoDB 多版本并发控制 (MVCC) 以不同于聚集索引的方式对待二级索引。 聚集索引中的记录就地更新它们的隐藏系统列指向undo log条目从中可以重建早期版本的记录。

与聚集索引记录不同,二级索引记录不包含隐藏的系统列,也不会就地更新。

当更新二级索引列时,旧的二级索引记录被删除标记,插入新记录,并最终清除删除标记的记录。 当二级索引记录被删除标记或二级索引页面被更新的事务更新时InnoDB 在聚簇索引中查找数据库记录。 在聚簇索引中,检查记录的 DB_TRX_ID如果记录在读取事务启动后被修改则从撤消日志(undo log)中检索记录的正确版本。