InnoDB的MVCC是通过每行后面保存两个隐藏的字段来实现的。一个用来记录行的创建时间,一个用来记录行的删除时间 ,存储的不是实际的时间值,而是系统版本号。
每开始一个新的事物,系统版本号都会自动递增。当前事务开始时的系统版本号,将会作为该事务的版本号,用来和查询到的每行记录的版本号做比较。
RR隔离级别下,MVCC具体操作:
-
select操作
InnoDB会根据以下两个条件进行检索:
a. 检索数据时候,只会检索出行版本号(创建版本号)小于或等于当前事务版本号的行。这样就可确保事务读取到的行,要么实在事务开始之前已经存在,要么是当前事务自己插入或修改的
b. 检索数据行的时候,行的删除标识要么为空,要么大于删除标识号大于当前事务版本号。这样可以确保事务读取到的行,在事务开始之前没被删除。
当同时满足a ,b两个条件的行,才能作为查询结果返回 -
Insert操作
InnoDB为新插入的每一行保存当前系统版本号作为行版本号 -
delete操作
InnoDB为删除的每一行保存当前系统版本号作为删除标识 -
update操作
InnoDB插入一行新纪录,并且保存当前系统版本号作为行版本号,同时保存系统版本号到原来的行作为删除标识
MVCC只在repeatable rea和read committed两个隔离级别下工作,其他两个隔离级别都和MVCC不兼容,因为read uncommitted总是读取最新的数据行,而不是符合当前事务版本的数据行;serializable则会对所有的读取行都加锁
InnoDB的一些杂记:
InnoDB采用MVCC来支持高并发,并实行了四个标准的隔离级别。其默认级别是RR(可重复读),并通过间隙锁(next-key locking)策略方式幻读的出现。间隙锁使得InnoDB不仅仅锁定查询涉及到的行,还会对索引中的间隙进行锁定,以防止幻影行的插入。— 摘自《高性能Mysql》