InnoDB 多版本
InnoDB 多版本
- InnoDB 是一个多版本的存储引擎。它保存数据行旧版本的信息以支持事务的并行和回滚的功能。这些记录的信息被保存在系统表空间或者回滚表空间中一个叫做回滚段的数据结构中。InnoDB 使用回滚段中的信息完成事务回滚所需的撤销操作。这些信息同样会被用来构建较早版本的数据行数据,并被使用以作为一致性读所需的数据行。
- InnoDB 会在存储在数据库中的数据行内部添加三个字段:
- 6 字节 DB_TRX_ID 字段表示最后一个插入或更新事务的事务标识。当然,删除操作内部会被以更新的方式特殊处理,使用特殊的位表示该数据行被标记为“已删除”。
- 7 字节 DB_ROLL_PTR 字段被称为滚动指针。滚动指针指向回滚段中写入的撤销日志记录。如果该数据行已被更新,撤销日志中的记录包含了重建这条数据被更新前的内容所需的信息。
- 6 字节 DB_ROW_ID 字段包含了刚插入的新数据行单调增长的行 ID 号。如果 InnoDB 自动生成一个聚集索引,聚集索引中包含行 ID 的数值。另外, DB_ROW_ID 不会出现在任何索引中。
- 回滚段中的撤销日志被区分为插入和更新撤销日志两种类型。插入撤销日志只在事务回滚时并且在事务提交时会被以最快的速度被销毁。更新撤销日志在一致性读的时候会被使用到,但是它们只有在 InnoDB 没有其他事务需要读该数据库中此行数据其他早期版本信息的快照时才会被销毁。
- 建议定期提交事务,包括只在一致性读时触发的事务。否则,InnoDB 无法销毁更新销毁日志的数据,此时回滚段可能增长得过大,导致其所存在的表空间被填满。
- 回滚段中撤销日志的物理大小会明显小于相关联的插入或更新的数据行大小。这可以通过回滚段使用空间来计算。
- 在 InnoDB 多版本架构中,当使用 SQL 语句删除数据时,该数据不会立刻被从数据库的物理存储中移除。InnoDB 只会在相关数据行的更新撤销日志中的删除操作写入被清除后才会物理删除该行及它的索引数据。这个删除操作叫做清理( purge ),这个操作通常很快,通常这个操作和使用 SQL 语句删除数据的时间顺序一致。
- 如果在小的批次中插入和删除的数据行是表数据行对应的较小比例,则清理线程可能开始延后并且表可能由于“被删除”行堆积增长得越来越大,导致磁盘瓶颈并非常慢。在这种情况下,限制新增数据的操作,并且通过调整系统变量 innodb_max_purge_lag 来分配更多的资源给清理线程。
多版本与二级索引
- InnoDB 多版本并发控制(MVCC)在处理二级索引上与处理聚集索引不同。聚集索引中的记录使用“原地”更新,并且它们可以重购出隐藏系统字段指向上一版本的撤销日志实体。与聚集索引不同,二级索引记录不饮食隐藏系统字段并且无法“原地”更新。
- 当更新二级索引字段,旧的二级索引记录被标记为删除,新记录被添加,被标记为删除的记录最终会被清理。当二级索引的记录被标记为删除或者二级索引页被新的事务更新,InnoDB 会在聚集索引中检索数据库记录。在聚集索引中,记录的 DB_TRX_ID 会被校验,并且如果该记录在读事务初始化后被修改的话,正确版本的记录会从撤销日志中被拾取出来使用。
- 如果二级索引被标记为删除或者二级索引页被新的事务更新,覆盖索引技术无法被使用。替代从索引结构中返回数值,InnoDB 从聚集索引中检索出记录。
- 然而,如果索引条件下推(ICP)优化机制是开启的,并且部分 WHERE 条件能被评估为可只使用索引中的字段,MySQL 服务依然会推动这部分的 WHERE 条件使用存储引擎里被评估为可使用的索引。如果没有找到匹配的记录,聚集索引检索会被取消。如果匹配记录找到了,即使饮食了被标记为删除的记录,InnoDB 同样从聚集索引中检索对应的记录。
更多动态请关注微信公众号 dbagrant