表锁、行锁和间隙锁
表锁
在整个数据表上对数据进行加锁和释放锁,在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如何判断:
MVCC版本链:
RC中的ReadView每一次select都会生成新的ReadView。(以select语句为单位)
RR中的ReadView每一次事务都会生成新的ReadView。(以事务为单位)