MySQL中的并发控制概览( 二 )


MVCC(Multiversion Concurrency Control)是侧重于读写并发的改善机制,它可以避免写操作堵塞读操作的并发问题,通过使用数据的多个版本保证并发读写不冲突的一种机制,它只是一种标准,并不是规定了明细的实现细节,所以在数据库方向上大体会有一些MVCC的不同实现 。
写-写的场景其实相对容易理解,为了保证在同一时间完成数据的一致性操作,我们需要通过锁的方式来控制,为了方便理解,整个过程简单理解是串行的,有一些改进的细节我们在后面会说 。
这里要先引出一个概念,就是2PL(Two-Phase Locking ,二阶段锁),这个过程我们举个例子就很容易理解了 。加锁阶段只加锁,解锁阶段只放锁,就好像我们呼吸一样,吸气,呼气,一张一弛,但是不会彼此交叉 。把这个过程细化到一个数据并发中的场景:
(1) 操作数据前,加锁,互相排斥,不允许其他并发任务操作 。
(2) 操作数据后,解锁,其他任务可以继续执行 。
这种锁定的方式相对比较单一而且粒度太粗,这样会导致在并发读任务都会阻塞,对于并发的性能影响是很大的,所以InnoDB实现了两种类型的行锁 。
l 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同的数据集的排他锁 。
l 排他锁(X):允许获得排他锁的事务更新数据,但是组织其他事务获得相同数据集的共享锁和排他锁 。
简单小结为:
l 共享锁(S)之间不互斥,读读操作可以并行 。
l 排它锁(X)是互斥关系,读写,写写操作不可以并行 。
一些常见的共享锁的使用方式有:
共享锁:
select * from table_name where .....lock in share mode
排他锁:
select * from table_name where .....for update
通过这一层的改进,可以对于读读并发的场景有了较好的支撑,但是写入的过程中,读任务还是会被阻塞,对于读写的操作还是存在瓶颈,所以在这个层面上引入了MVCC,在详细展开之前,我们需要了解下MVCC并发控制中的两类读操作,快照读(Snapshot Read)和当前读(Current Read),其中快照读读取的是数据的可见版本,可能是数据的历史镜像,这个过程是不加锁的,而当前读读取的是最新的版本,会加上锁,保证其他事务不会再修改这条记录 。
比如我们触发了一条select操作: select * from test where id=100; id为主键,这条语句对应的操作就是快照读,而我们上面刚刚列举的共享锁和排它锁的SQL还有常见的DML都属于当前读,操作过程中会读取当前最新的版本,保证其他事务不能修改当前记录 。
我们通过思维导图的形式简单对并发控制技术做个总结,如下图所示 。
 

MySQL中的并发控制概览

文章插图
 

【MySQL中的并发控制概览】


推荐阅读