MySQL锁

前言

今天字节的面试问到了MySQL的锁,自己回答的含糊不清,所以重新学习一遍做一个梳理。这里讲的是MySQL 5.7在InnoDB引擎下的锁机制。

概述

总的来说,InnoDB共有七种类型的锁:

  • 共享锁(S)/独占锁(X)
  • 意图共享锁(IS)/意图独占锁(IX)
  • 记录锁
  • 间隙锁
  • 临键锁
  • 插入意图锁
  • 自增锁

1.共享锁/独占锁

这两个锁都是行级锁

  • 共享锁(S):允许一个事务去读一行
  • 独占锁(X):允许一个事务更新或删除一行

互斥性:

  • S锁定之间不互斥,即两个事务可以同时获取该行的S锁
  • X锁定与其他任何锁互斥,即一个事务获得该行的X锁,其他事务对该行的X/S锁都不被马上许可,需要等待原本事务的完成

2.意图锁

InnoDB支持多间隔尺寸锁定,它允许记录锁和对整个表的锁共存。要实现多间隔级别尺寸的锁定,需要一种额外的锁,这种锁被称为意图锁。意图锁是表级锁。

先提前声明一个意图,并获取表级别的意图锁(意图共享锁/意图独占锁),如果获取成功,对该表的某些行加锁(S/X)。

意向锁协议:

  • 在假设的事务可以获得对某假定行的S锁之前,他必须首先获得对包含改行的一个IS锁或者更强的锁。
  • 在假设的事务可以获得对某假定行的X锁定之前,他必须首先获得对包含改行的表的一个IX锁定。

这些结果可以用一个兼容矩阵来表示:

在这里插入图片描述

客户端A获得对行的S锁:
在这里插入图片描述

接着客户端B尝试从该表删除该行,

在这里插入图片描述
删除要求一个X锁定,因为这个锁定不兼容客户端A持有的S锁定,所以X锁定不被允许,所以请求进入对行及客户端阻挡的锁定请求队列。(如上图,回车后,MySQL没有任何动作)

最后客户端A也试图删除该行:

因为客户端A需要一个X 锁定来删除该行,所以在这里发生死锁。尽管如此,锁定请求不被允许,因为客户端B已经有一个对X锁定的请求并且它正等待客户端A释放S锁定。因为客户端B之前对X 锁定的请求,被客户端A持有的S锁定也不能升级到X锁定。因此,InnoDB对客户端A产生一个错误,并且释放它的锁定。在那一点上,客户端B的锁定请求可以被许可,并且客户端B从表中删除行。

3.记录锁

记录锁是一个在索引行记录的锁。

例如:select * from tb1 where id = 1; 如果在id上的索引被用到,防止其他任何事务变动id=1的行。记录锁总是在索引行上加锁,即使一个表没有索引,这时InnoDB也会设置一个隐藏的聚集索引,这是InnoDB必须要有索引的一个原因。(还有其他原因是InnoDB采用B+树索引,会根据主索引建立一个B+树)。

当查询字段没有索引时,例如:update tb1 set age = 20 where name = ‘wule’;如果name字段不存在索引,那么就会锁住整个表。否则就锁住该行。

4.间隙锁

间隙锁封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者索引最后一天记录的范围。一般作用于范围查询:>,<,between…and…

select * from tb1 where id between 1 and 4;
# 这个SQL语句会封锁区间(1,4),防止其他事务在该区间插入数据

对于使用唯一索引来搜索一个的语句,不产生间隙锁定

间隙锁的主要目的是为了防止其他事务在间隔中插入数据,以导致“不可重复读”。如果把事务的隔离级别降为读未提交(RC),间隙锁会自动失效。

5.临键锁

临键锁,是记录锁和间隙锁的组合,它的封锁既包含索引记录也包含索引区间。

默认情况,InnoDB使用next-key locks来锁定记录。但当查询的索引含有唯一属性的时候,next-key会进行优化,将其降级为记录锁。即锁住记录本身。

如果对tb1表中的name字段添加一个普通索引。然后执行:

# 事务A
select * from tb1 where name = 'wule' for update;

# 事务B
insert into tb1 values(0, 'xc');

因为name的索引是普通索引,即使命中了name=‘wule’,也会锁住该行及以前的记录。

临键锁的目的是为了避免幻读,如果把事务的隔离级别降为RC,临键锁会失效。

6.插入意图锁

插入意图锁是间隙锁的一种,它是专门针对insert操作的,多个事务在同一个索引和同一范围内插入数据,如果插入的位置不冲突,则不会彼此阻塞。

7.自增锁

自增锁是一种特殊的表级锁。事务插入到具有AUTO_INCREMENT列的表中,那么其他事务必须等待改事务执行完毕,以便该事务插入的是连续的主键值。

总结

按粒度划分为:

  • 表锁:意图锁、自增锁
  • 行锁:记录锁、间隙锁、临键锁、插入意图锁

间隙锁和临键锁只在RR以上的隔离级别生效,RC下会失效。

改事务执行完毕,以便该事务插入的是连续的主键值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值