MVCC是multiversion concurrency control的缩写,提供MySQL事物隔离级别下无锁读,例如一个事物在执行update等修改数据的sql,并未提交时其他事物进行数据读取是不影响的,而且读取内容为数据变更之前的数据。

 

mvcc多本版快照由innodb的rollback segment构照的,一个sql进行查找数据当查找到某一个数据需要到回滚段中查找数据时,就会根据当前页上行数据的一个指针到回滚段中查找对应数据,在innodb的表主键中都会存在三个隐藏的字段:

    DB_TRX_ID:该字段存储最后一个修改该行数据的事务ID,占用6byte的空间,MySQL的delete操作是标记删除,所以对应行数据的该字段就为一个删除标记。

    DB_ROLL_PTR:该字段就记录执行roll segment的指针信息,当事务需要rollback时就通过该字段寻找记录重新构照行数据,该字段占用7byte空间。

    DB_ROW_ID:记录每个行ID,该ID值为单调递增型整数,在innodb表指定了主键之后DB_ROW_ID存在于主键索引上,如果无主键该值就不会存在,占用6byte空间。

 

在一个sql进行查询时,读取到一行数据的DB_TRX_ID值和自己事物ID的对比,假如隔离级别为MySQL的默认级别,就只读取该ID值小于本身事物ID的数据,其余数据就需要通过DB_ROLL_PTR的信息到回滚段中读取。MVCC是否起到相应的作用需取决于数据库隔离级别的配置。

 

在insert和update、delete的操作是有区别的,一个insert语句插入数据再rollback就是直接对undo log的删除,网上关于这部分的教程比较少,因为他并不会影响其他事物的读取操作,而update、delete操作是在原有数据做更改,可能有其他事物在对该行数据做读取操作,所以update、delete产生的undo log数据是由内部线程自动清理,在该数据无任何事务在使用时清理掉,所以在undo log中insert和update、delete产生的数据存于不同位置。

 

上面说了数据的update、delete、insert操作,都会根据主键上的隐藏列来判断和查找,但是辅助索引并不存在隐藏列,辅助索引就是有索引列和主键列组成的一个小表,这该怎么判断呢?辅助索引区别在于假如是一个update操作步骤为:

    1、标记删除原纪录

    2、插入新纪录

    3、对应主键做上面的隐藏字段修改,行数据更新,原行数据移入回滚段

一个查询语句在利用辅助索引进行查找时,发现有个标记删除或者有新数据就会到主键扫描对应的DB_TRX_ID值对比当前事物ID大小,是否利用DB_ROLL_PTR进行读取数据。辅助索引的delete、insert也是类似,只是一个没有新纪录,一个没有标记删除记录。