MVCC与锁
InnoDB存储引擎默认的事务隔离级别是REPEATABLE_READ, 在该隔离级别下,其采用Next-Key Locking的方式来加锁。
Innod存储引擎的普通SELECT操作使用一致性非锁定读,也即快照读。
当一个事务想对这条记录做改动时,首先会看看内存中有没有与这条记录关联的锁结构,当没有的时候就会在内存中生成一个锁结构与之关联。UPDATE,INSERT,DELETE等操作就会在内存中生成锁结构。
要理解MVCC,我们首先要明白MVCC解决的是什么问题?
既想保持事务的隔离性,又想让服务器在处理访问同一数据的多个事务时性能尽量高些,读和写都加锁的效率太低了,鱼和熊掌不可得兼,舍一部分隔离性而取性能者也。
所谓的
MVCC(Multi-Version Concurrency Control ,多版本并发控制)指的就是在使用READ COMMITTD、REPEATABLE READ这两种隔离级别的事务在执行普通的SEELCT操作时访问记录的版本链的过程,这样子可以使不同事务的读-写、写-读操作并发执行,从而提升系统性能。READ COMMITTD、REPEATABLE READ这两个隔离级别的一个很大不同就是:生成ReadView的时机不同,READ COMMITTD在每一次进行普通SELECT操作前都会生成一个ReadView,而REPEATABLE READ只在第一次进行普通SELECT操作前生成一个ReadView,之后的查询操作都重复使用这个ReadView就好了。
这段信息量非常大,有几个关键点。
MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作
MVCC解决的是不同事务读-写,写-读操作的并发执行,读-读不冲突,而写-写一般采取加锁。
在使用RC和RR隔离级别下
使用普通select操作,也即快照读,不能是当前读,当前读是通过加锁解决冲突的
那么当前读呢?
实验表明,当前读select for update是会阻塞的
当前读读取的数据库记录,都是
当前最新的版本,会对当前读取的数据进行加锁,防止其他事务修改数据。是悲观锁的一种操作。为什么会阻塞呢?
InnoDB存储引擎默认的事务隔离级别是REPEATABLE_READ, 在该隔离级别下,其采用Next-Key Locking的方式来加锁。
在事务中,SELECT FOR UPDATE会锁上范围,导致INSERT阻塞。
同理,INSERT也会锁上范围,导致SELECT FOR UPDATE阻塞。
至此,终于是理清了MVCC和锁的关系。
总结,MVCC到底是为什么解决什么问题,答解决的是不同事务读写冲突的问题,快照读在undo日志记录的版本链中,找到在快照读之前已经提交的事务。
而当前读要取当前最新的版本,会对当前的数据进行加锁,防止其他事务修改数据。
mysql是怎样运行的,mysql技术内幕