15.3 Innodb多版本

InnoDB是一个多版本的存储引擎:它保存有关已更改行的旧版本的信息,以支持并发和回滚等事务功能。此信息以称为回滚段的数据结构(在Oracle中的类似数据结构)存储在表空间中。 InnoDB使用回滚段中的信息来执行事务回滚中所需的回滚操作。它还使用该信息构建行的早期版本用于一致性读。

在内部,InnoDB为存储在数据库中的每一行添加三个字段。6字节的DB_TRX_ID字段用来记录插入或更新该行的最后一个事务的事务标识符。删除操作被视为更新操作,行中的特殊位标记位用来标记行已被删除(commit前)。每行还包含一个7字节的被称为滚动指针的DB_ROLL_PTR字段。滚动指针指向写入回滚段(rollback segment)的一条undo日志记录。如果行被更新,则undo日志记录了重建行更新前的内容所需要的信息。6字节的DB_ROW_ID字段记录在新行插入时单调增加的行ID。如果InnoDB自动生成聚簇索引,则索引包含行ID值。否则,DB_ROW_ID列不会出现在任何索引中。

Rollback segment中的undo日志分为insert和update undo日志。Insert undo日志只用于事务回滚,当事务提交后可以立即丢弃。Update undo日志还用于一致性读,但是,当innodb当前的一致性读快照中,没有事务需要构建数据库的早起版本,则update undo日志此时可以被丢弃。

定期提交事务,包括那些一致读的事务。否则,InnoDB无法丢弃update undo日志中的数据,并且回滚段可能会变得太大,从而占满表空间。

回滚段中的undo log记录的物理大小通常小于相应的插入或更新的行。可以使用此信息计算回滚段所需的空间。

在InnoDB多版本控制中,当您使用SQL语句删除行时,并不会立即从数据库中物理删除该行。InnoDB只有在dicard删除操作的update undo log之后,才会物理删除相应的数据及其索引。这种删除操作称为purge,速度非常快,通常与执行删除的SQL语句的同时完成。

如果在表中以大致相同的速率分批删除或插入数据,则purge thread可能开始滞后,并且由于所有标记删除行,表会变得越来越大,并导致磁盘性能下降变的很慢。在这种场景中,可以限制新的行操作,并通过设置系统参数innodb_max_purge_lag来为purge thread分配更多的资源。参考15.13 InnoDB启动选项及系统参数

多版本和二级索引

Innodb多版本并发控制(MVCC)以不同于聚簇索引的方式处理二级索引。聚集索引中的记录就地更新,其隐藏的系统列指向undo日志,从中可以重建行的早期版本。与聚簇索引列不同,二级索引列不包含隐藏系统列,也不是就地更新。

二级索引列更新时,二级索引列记录被标记删除,新行记录插入,标记删除列最终会被purged。当二级索引记录被标记删除或二级索引页面被更新的事务更新时,InnoDB在聚簇索引中查找数据库记录。在聚簇索引中,会检查记录的DB_TRX_ID,如果在启动读取事务后,有事务对其进行修改,则会从undo日志中检索正确的记录版本。如果二级索引记录被标记为删除或二级索引页面由较新的事务更新,则不会使用覆盖索引。

但是,如果启用index condition pushdown (ICP)优化,并且WHERE条件的某些部分可以使用索引中的字段,则MySQL服务器会将WHERE条件的这一部分向下推送到使用索引评估它的存储引擎层。如果未找到匹配的记录,则避免聚簇索引查找。如果找到匹配的记录,即使在删除标记的记录中,InnoDB也会在聚簇索引中查找记录。

参考

MySQL · 特性分析 · Index Condition Pushdown (ICP)

MySQL 5.6 新功能之 Index Condition Pushdown (ICP)

results matching ""

    No results matching ""