MVCC:
1什么是MVCC?
MVCC是一种多版本并发控制机制。
2 MVCC的作用?
锁的开销毕竟很大,所以使用 MVCC + 行锁 的方法解决幻读,降低系统开销
3 MVCC的原理:
保存数据某个时间点的快照来实现。也就是说不管一个事务执行了多久,同一个事务中看到的数据始终一致(如果事务开始时间不同,很有可能相同时间下不同事务会看到不同的数据)
4 InnoDB中的MVCC的实现:
4.1 数据行后面的隐藏的字段
MVCC会在每行记录后面保存2个隐藏的列:行的创建版本号,行的过期版本号 (每次开启一个新事务,系统版本号都会自动递增)
例如在RR(可重复读)级别下:(MVCC仅兼容于可/不可重复读这两个级别下)
SELECT会查找创建版本号 <= 当前事务版本号,过期版本号 >= 当前版本号的数据行 (这样找到的数据在事务开始之前已经存在且没有被删除,PS:这也就是为什么innodb相对于myisam不适合频繁去读的原因之一)
INSERT会为每个新增行记录当前系统版本号作为行创建版本号。
DELETE会为每个删除行的记录当前系统版本号作为行的过期版本号。
UPDATE是insert和delete操作的组合,insert的行保存当前版本号为行创建版本号,delete则保存当前版本号到原来的行作为过期版本号。由于旧数据并不真正的删除,innodb会开启一个后台线程执行清理工作,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫做purge。
4.2 快照读与当前读:
快照读(MVCC):innodb的RR级别会在开启事务的第一次select操作时(判断创建/过期版本号)生成一张快照,以后这个事务的所有select操作都会从这个快照中读数据。(至少其他事务修改数据不会对本次事务产生影响,也算是解决了部分的幻读问题 -_- !)
当前读(next-key):update、insert、delete会读取最新的数据并上锁(next-key锁),但是这样当某个事务上了写锁之后,其他事务仍然可以读快照。
4.3 undolog与redolog:
undolog:可以理解成要操作的数据的备份(回滚时用到,保证事务的原子性)。
快照 = undolog + 未修改的表的数据(可以认为当 delete 一条记录时,undo log 中会记录一条对应的 insert 记录)
redolog:记录已经commit,但是没有完全写到磁盘中的数据(说白了就是持久化)
整体大致的执行过程:begin -> 用排他锁锁定该行进行操作 -> 记录redo log -> 记录undo log -> 修改当前行的值,写事务编号(回滚则是指针指向undo log中的修改前的行)