Mysql加锁处理分析-基于InnoDB存储引擎

MVCC


MySQL INNODB存储引擎,实现的是基于多版本的并发控制协议——MVCC (Multi-VERSION Concurrency Control)。MVCC最大的好处,相信也是耳熟能详:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是很是重要的,极大的增长了系统的并发性能,这也是为何现阶段,几乎全部的RDBMS,都支持了MVCC。数据库

在MVCC并发控制中,读操做能够分红两类:快照读 (snapshot read)与当前读 (current read)。快照读,读取的是记录的可见版本 (有多是历史版本),不用加锁。当前读,读取的是记录的最新版本,而且当前读返回的记录,都会加上锁,保证其余事务不会再并发修改这条记录。并发

在一个支持MVCC并发控制的系统中,哪些读操做是快照读?哪些操做又是当前读呢?以MySQL InnoDB为例:性能

快照读:简单的SELECT操做,属于快照读,不加锁。(固然也有例外,下面会分析)spa

  • select * from table where ?;blog

当前读:特殊的读操做,插入/更新/删除操做,属于当前读,须要加锁。事务

  • select * from table where ? lock in share mode;ip

  • select * from table where ? for update;get

  • insert into table values (…);table

  • update table set ? where ?;date

  • delete from table where ?;

为何将 插入/更新/删除 操做,都归为当前读?能够看看下面这个 更新 操做,在数据库中的执行流程:

从上图能够看出,当UPDATE SQL被发给MySQL后,MySQL SERVER会根据WHERE条件,读取第一条知足条件的记录,而后INNODB引擎会将第一条记录返回,并加锁 (current READ)。待MySQL SERVER收到这条加锁的记录以后,会再发起一个UPDATE请求,更新这条记录。一条记录操做完成,再读取下一条记录,直至没有知足条件的记录为止。所以,UPDATE操做内部,就包含了一个当前读。同理,DELETE操做也同样。INSERT操做会稍微有些不一样,简单来讲,就是INSERT操做可能会触发UNIQUE KEY的冲突检查,也会进行一个当前读。

:根据上图的交互,针对一条当前读的SQL语句,INNODB与MySQL SERVER的交互,是一条一条进行的,所以加锁也是一条一条进行的。先对一条知足条件的记录加锁,返回给MySQL SERVER,作一些DML操做;而后在读取下一条加锁,直至读取完毕

 

2PL


传统RDBMS加锁的一个原则,就是2PL (二阶段锁):Two-Phase Locking。相对而言,2PL比较容易理解,说的是锁操做分为两个阶段:加锁阶段与解锁阶段,而且保证加锁阶段与解锁阶段不相交。下面,仍旧以MySQL为例,来简单看看2PL在MySQL中的实现。

从上图能够看出,2PL就是将加锁/解锁分为两个彻底不相交的阶段。加锁阶段:只加锁,不放锁。解锁阶段:只放锁,不加锁。

相关文章
相关标签/搜索