InnoDB 是一个多版本的存储引擎:为了支持事务的一些特性诸如并发和回滚,它保持着被修改行的旧版本信息.这些信息被存储在一个被叫做 "回滚段" 的表空间中(跟 Oracle 中的回滚段类似).InnoDB 在回滚段中用这些信息来执行 undo 操作,以此支持事务回滚.它也用这些信息来构造行的更早的版本,以此支持一致性读.
在内部,InnoDB 为数据库中存储的每一行添加三个字段.一个 6 字节的 DB_TRX_ID 字段来表示插入或者修改这一行的最后一个事务的事务标示符.delete 在内部被当做 update 来对待,就是在行的特定位做一个标记,以表明这一行已经被删除.每一行还包含一个被叫做 "roll pointer" 的 7 字节的 DB_ROLL_PTR 字段.这个 roll pointer 被指向一个写在回滚段中的 undo log.如果行被修改了,那么这个 undo log 记录包含的信息必须先于行修改被重新修改.一个 6 字节的 DB_ROW_ID 字段包含一个当行被插入的时候单调递增的行 ID.如果 InnoDB 自动生成了一个聚集索引,那么这个索引包含行 ID 值,否则 DB_ROW_ID 列不会出现在任何索引中.
回滚段中的 undo logs 被划分为 insert undo logs 和 update undo logs.insert undo logs 只有在事务回滚的时候才会用到它,并且在事务提交以后它就被丢弃了.update undo logs 用在一致性读的时候.
定期提交你的事务,包括哪些只有一致性读的事务.否则,InnoDB 不能从 update undo logs 中丢弃数据,并且回滚段可能会增长得很大,填满你的表空间.
在 InnoDB 多版本中,当你用 SQL 语句删除的时候,这一行并不是立即从数据库中被物理删除.只有当它为了删除丢弃了 update undo logs 的时候,InnoDB 才会物理删除这一行和它的索引记录.这种删除操作被叫做 purge,并且它的速度相当快
Multi-Versioning and Secondary Indexes
InnoDB 多版本并发控制(MVVC)对待二级索引和聚集索引时不同的.一条记录的聚集索引在原地被更新,它们的执行 undo log 的隐藏系统列会被重新构造.不像聚集索引记录那样,二级索引记录不包含隐藏的系统列,它们也不会在原地被更新.
当一个二级索引记录被更新的时候,旧的二级索引记录被标记为删除,新的索引记录被插入,并且被标记为删除的索引记录最终被 purge.当一个二级索引记录被标记为删除或者二级索引页被一个新的事务更新的时候,InnoDB 用聚集索引查找数据库记录.在聚集索引中,记录的 DB_TRX_ID 字段被检查,并且记录的正确版本会被从 undo log 中检索出来,即使记录在事务初始读取以后被修改.
小结:
1,InnoDB 在回滚段中维护着被修改行的旧的版本信息
2,回滚段中的 undo logs 分为 insert undo logs 和 update undo logs.并且 undo log 日志写入优先.
3,在内部,delete 被当做 update 来对待.它是将旧的行标记为删除,然后插入新的行.
4,当在 SQL 语句执行 DELETE 的时候并不是立即从数据库中删除这条记录.只有当它丢弃 update undo logs 的时候,该记录及其索引记录才会被物理删除.
5,InnoDB 给数据库中的每一行记录添加三个字段
DB_TRX_ID:表明插入或者修改这一行的最后一个事务的事务标识符
DB_ROLL_PTR:指向回滚段中的一个 undo log 记录
DB_ROW_ID:单调递增的行 ID.(PS:如果没有明确定义聚集索引,那么会自动生成一个聚集索引,这个时候自动生成的聚集索引的值就是 DB_ROW_ID)
6,MVCC 下的二级索引和集聚索引时不同的.二级索引记录既不包含隐藏的系统列,也不会在原位置被更新.与之相反,聚集索引记录才会包含隐藏的指向 undo log 记录的系统列,而且聚集索引时在原来位置上被更新的.
7,当一个二级索引列被更新的时候,旧的二级索引记录被标记为删除,同时插入一个新的二级索引记录.
8,由此可见,undo logs 中不仅包含记录的 undo log 还包含索引记录的 undo log.
参考 https://dev.mysql.com/doc/refman/5.7/en/innodb-multi-versioning.html
来源: http://www.bubuko.com/infodetail-2477205.html