MVCC学习

122 阅读2分钟

表锁、行锁和间隙锁

表锁

在整个数据表上对数据进行加锁和释放锁,在MySQL中有两种表级锁模式:表共享锁(读操作)、表独占写锁(写操作)。

行锁

在数据行上对数据进行加锁和释放锁。在InnoDB存储引擎中,有两种类型的行锁:共享锁排他锁共享锁允许一个事务读取一行数据,但不允许一个事务对加了共享锁的当前行增加排他锁。排他锁允许当前事务对数据进行CRUD操作,不允许其他事务对增加了排他锁的数据行增加共享锁排他锁

  • 行锁主要加在索引上,如果对非索引的字段设置条件进行更新,行锁可能会变成表锁。
  • InnoDb的行锁是针对索引加锁,不是针对记录加锁。
  • 锁定某一行时,可以使用lock in share mode 命令来指定共享锁,使用for update命令来指定排他锁(select * for account where id = 1 for update)。

间隙锁

间隙锁就是对两个值之间的间隙加锁。MySQL的默认隔离级别是可重复读,在可重复读隔离级别下会存在幻读的问题,而间隙锁在某种程度下可以解决幻读的问题。

  • 间隙锁只有在可重复读事务隔离级别下才会生效。

InnoDB中的MVCC原理

MVCC(多版本并发控制)最终的目的实现非阻塞读操作,写操作也只会锁定必要的数据行。 本质上,MVCC机制保存的是数据库中数据在某一个时间点上的数据快照。

读已提交(RC)和可重复读(RR)两种隔离级别都是基于MVCC

ReadView:定义在MVCC的版本链中如何选择可以版本。参数如下

  • m_ids:当前在生成readview时当前系统中活跃的读写事务的事务id列表
  • min_trx_id:m_ids中最小的值
  • max_trx_id:表示生成readview时系统中应该分配给下一个事务的id
  • creator_trx_id:表示生成改readview的事务的事务id

ReadView如何判断:

image.png

MVCC版本链:

image.png

RC中的ReadView每一次select都会生成新的ReadView。(以select语句为单位)

RR中的ReadView每一次事务都会生成新的ReadView。(以事务为单位)