【MySQL】Innodb的多版本一致性读
在前面Innodb事务隔离级别中可以看到,在Innodb默认的的重复读(repeatable read)事物隔离级别下,可以实现重复读。和串行读(serializable)事物隔离级别实现重复读不同的是,串行读(serializable)为实现重复读,会在SELECT的时候隐式的对行添加共享读锁。而Innodb在实现过程并不对行加锁,而是通过使用多版本并发控制(MVCC,Multiviersion Concurrency Control)的技术来实现Consistent Nonlocking Reads。
关于Innodb的多版本一致性读的实现机制和Oracle的实现很类似,都是通过rollback segment来实现的,具体如下说明:
1、rollback segment的存放位置
在Innodb的逻辑存储结构中也有表空间tablespace/segment/extent的概念,具体结构层次见下图(图片来自<InnoDB Internals: InnoDB File Formats and Source Code Structure>)。默认情况下,所有的数据都放到共享表空间ibdata1中,如果启用了参数innodb_file_per_table的话,每张表内的数据可以放到自己独立的放到一个表空间中。不管是否开启该参数,rollback segment都是存放在共享表空间中。

2、rollback segment的作用
rollback segment中存放发生改变行的老版本信息,过程如下图(来自Oracle的一张示图):

rollback segment主要用于:
(1)当发生事物回滚,需要使用rollback segment中的这些信息用于进行undo操作。
(2)通过这些信息,可以实现对应版本的一致性读,从而实现了在innodb默认隔离级别下的可重复读。
在实现多版本一致性读的时候,Innodb的行会额外增加三个字段DB_TRX_ID/DB_ROLL_PTR/DB_ROW_ID来完成。要查看这3个字段参考之前笔记:《MySQL查看InnoDB存储引擎的表和索引内部结构》。
其他的可以参考:
http://www.mysqlsupport.cn/innodb-multi-version/
另外,看到网上关于Innodb的共享表空间增长迅速,其中主要原因是产生大量的回滚信息:
Running Transaction which does a lot of changes.
Running Very Long Transaction.
Purge Thread Falling Behind.
具体见<Reasons for run-away main Innodb Tablespace>,<Purge Thread Spiral of Death>