MySQL之多版本并发控制(MVCC)
在程序员的思维里,并发控制永远都是值得讨论的话题。这里我就不过多的去讲解并发控制的基本概念了
●基本概念
MVCC:Multi-VersionConcurrencyControl多版本并发控制。笔者用自己的话对MVCC做一个总结:通过某个时间点上的数据快照对数据的版本控制,目的是为了避免使用各种锁影响并发性能
●MySQL锁机制
说到锁,MySQL里提供了几种锁机制
读写锁
表锁
行级锁
笔者不来一一解释这几种锁的基本概念了,百度谷歌应该会有不少。笔者这里需要说一点,不管使用了什么锁,锁的方式都是隐式锁定的,不需要手动去做任何事情。因为笔者曾经和人讨论MySQL锁机制的时候曾有人提出使用forupdate的方式锁定。这种方式实际为MySQL显示锁定,MySQL的文档里有说明此方法并不推荐使用的。实际上也并不需要使用,原因上面已经讲过了。所有的锁都是隐式锁定的
MySQL提供了两种显示锁定的方式
select * for update select * lock in share mode
程序员们千万记住,以上的语句完全没有必要,不仅如此,还会极为浪费性能。实际上InnoDB的行级锁已经完全处理OK了
●MVCC控制
基于性能考虑,实际MySQL大多的事务型存储引擎的实现都不是简单的行级锁,而是大量的使用了MVCC。
MVCC的实现,是通过数据保存数据在某个时间点的快照来实现的。也就是说,不管需要执行多长时间,每个事务看到的数据都是一致的。根据食物开始时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。
不同的存储引擎的MVCC的实现方式是不同的,最典型的有乐观并发控制和悲观并发控制。
InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的,这两个列,一个保存了行的创建版本号,一个保存了行的过期版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事物的版本号,用来和查询到的每行记录的版本号进行比较。
下面看一下REPEATABLEREAD隔离级别下,MVCC具体是如何操作的
SELECT
InnoDB会根据一下两个条件检查每行记录
a.InnoDB至查找版本早于当前事务版本的数据行,这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的。
b.行的删除版本要么未定义,要么大于当前事务版本号。这个可以确保事务读取到的行,在事务开始之前未被删除
只有符合以上两个条件的记录,才能返回作为查询结果
INSERT
InnoDB为新插入的每一行保存当前系统版本号作为行版本号
DELETE
InnoDB为删除的每一行保存当前系统版本号作为行删除标识。
UPDATE
InnoDB为插入一行新纪录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识。