MVCC处理并发事务与锁

MVCC与锁

InnoDB存储引擎默认的事务隔离级别是REPEATABLE_READ, 在该隔离级别下,其采用Next-Key Locking的方式来加锁。

Innod存储引擎的普通SELECT操作使用一致性非锁定读,也即快照读。

当一个事务想对这条记录做改动时,首先会看看内存中有没有与这条记录关联的锁结构,当没有的时候就会在内存中生成一个锁结构与之关联。UPDATE,INSERT,DELETE等操作就会在内存中生成锁结构。

要理解MVCC,我们首先要明白MVCC解决的是什么问题?

既想保持事务的隔离性,又想让服务器在处理访问同一数据的多个事务时性能尽量高些,读和写都加锁的效率太低了,鱼和熊掌不可得兼,舍一部分隔离性而取性能者也。

所谓的MVCC(Multi-Version Concurrency Control ,多版本并发控制)指的就是在使用READ COMMITTDREPEATABLE READ这两种隔离级别的事务在执行普通的SEELCT操作时访问记录的版本链的过程,这样子可以使不同事务的读-写写-读操作并发执行,从而提升系统性能。READ COMMITTDREPEATABLE READ这两个隔离级别的一个很大不同就是:生成ReadView的时机不同,READ COMMITTD在每一次进行普通SELECT操作前都会生成一个ReadView,而REPEATABLE READ只在第一次进行普通SELECT操作前生成一个ReadView,之后的查询操作都重复使用这个ReadView就好了。

这段信息量非常大,有几个关键点。

MVCC只在 READ COMMITTEDREPEATABLE 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技术内幕


版权声明:本文为Humphrey_1125原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。