三个额外域
名称 | 长度/Byte | 用途 |
---|---|---|
DB_TRX_ID | 6 | 最后插入/修改该行的事务ID |
DB_ROLL_PTR | 7 | 历史数据(undo log)指针 |
DB_ROW_ID | 6 | 自增行号,只在使用默认自增的时候才会出现 |
此外,还有一个删除标志位,用于表示数据已被删除,然而并没有写该标志位的具体位置,需要看看源码
Undo Logs
Undo logs有两种,insert undo logs & update undo logs
insert undo logs
仅用于事务回滚,且在事务提交后就可以回收。有点疑惑具体的使用场景
update undo logs
用于一致性读,但是只有在没有事务会读到该数据的前提下才能回收。主要用于提供不同时间点的快照
Notice
周期性将事务提交是一个好习惯,否则InnoDB不知道现在应该回收哪些数据,进而可能导致rollback segment太大
Space
undo log所占空间一般比常规的行要小,具体计算方法未知
Delete
在InnoDB的MVCC中,删除行时只会加上一个标志位,并不是马上就物理删除的,只有在没有事务会再读到该数据时,才会用非常快的速度将其从rollback segment物理删除(purge)。具体的触发条件是,删除该行的update undo log被回收的时候,进行purge操作。
注意,以保证服务质量,purge线程只有在没有数据写入的情况下运行,所以如果边写边删,purge线程将会一直被延迟执行,最终导致数据库会越来越大。具体延迟时间,通过参数innodb_max_purge_lag调整。
MVCC和辅助索引
主索引进行更新的时候,如前文所示,会将当前数据拷贝到rollback segment中,再原地修改当前的数据。由于辅助索引不具备TRX_ID等额外列,所以做不到原地修改的效果。
辅助索引修改流程
- 旧索引项被标记为删除
- 插入新索引
- 删除旧索引
删除时被访问
当被标记删除的索引项被访问到时,InnoDB会先去找主索引,再检查上文中的那一堆DB_TRX_ID等。如果DB_TRX_ID不对,则会放弃使用辅助索引,直接去主索引里面找(遍历)
查询优化
当Index Condition Pushdown优化被打开时,而且刚好Where项里的内容能够用索引找到,MySQL上层服务会直接把整个Where语句推给底层的InnoDB引擎,InnoDB会先去索引里面找有没有符合项,如果没有,那就认为这个Where啥也没选中,返回空;如果找到了,即使被标记为删除,InnoDB还是会去主索引里面再确认一下DB_TRX_ID和其他使用该辅助索引无法确定的判断条件等信息。