MySql锁知识记录积累(一)

1.关于脏读、幻读和不可重复读

脏读:一个事务A读取到了另一个事务B未提交的数据,叫做脏读
不可重复读:事务A被事务B干扰到了!在事务A范围内,两个相同的查询,读取同一条记录,却反返回了不同的结果,即不可重复读
幻读:事务A查询一个范围内的结果集,另一个并发事务B往这个范围中插入/删除了数据,并提交。然后事务A再次查询,结果查询到了不同的结果,这就是幻读。

2.事务隔离级别


在并发情况下,读未提交的事务隔离级别下,是不加锁的会存在 脏读、幻读和不可重复读的问题

3.InnoDB七种锁介绍

3.1共享/排他锁

InnoDB存储引擎实现了两种标准的行级锁:共享锁-Share(简称S锁)、排他锁(简称X锁)

  • 共享锁:在事务想要读取一条记录的时候,需要先获取该记录的共享锁。
  • 排他锁:在事务想要修改一条记录的时候,需要先获取该记录的排他锁。

共享锁存在的意义

  • 存在若干个事务想要读取一条记录,需要先获得该记录的共享锁,是为了避免该记录被其他事务所修改。

排他锁存在的意义

  • 当一个事务想要修改一条记录,需要先获得该记录的排他锁,此时其他事务无法读取该数据,直到排他锁释放。

3.2意向锁

意向锁解释:不与行级别锁冲突的表级锁。未来某个时刻,事务可能需要加共享锁或者排他锁的时候,先提前声明一个意向。是一个表级别的锁。

为什么需要意向锁?

  • 假设一个事务A获取了表中一行数据的排他锁
  • 此时事务B想要读取全表数据,需要对整张表加共享锁,因此需要保证表中不存在排他锁
  • 问题来了
    • 事务B想要判断表中是否存在排他锁,难道要全表遍历?
    • 为了解决该问题,因此有了意向锁

实际运行过程

  • 当一个事务A想要对表中的数据进行 读取/修改 的时候,需要向增加一个全表级别的 意向共享锁/意向排他锁
  • 此时其他事务想要对全表中的数据进行修改,就会发现表中存在全表级别的 意向锁,从而不需要避免了全表找锁

3.3记录锁

记录锁是粒度最小的锁,仅仅锁住一行。
记录锁加在索引上,如果一张表中没有索引,InnoDB会隐式创建一个索引,并用该索引加记录锁。
记录锁关键词lock_mode X locks rec but not gap

3.4间隙锁(Gap Lock)

间隙锁是一种加在两个索引之间的锁,或者加在第一个索引之前,最后一个索引之后的间隙,锁住的是一个区间。
lock_mode X locks gap before rec
为了解决幻读问题
间隙锁左右都是开区间

当SQL语句查询范围数据的时候,会对查询的范围区间加上间隙锁。
此时,其他事务无法在加上了间隙锁的范围区间内插入新的数据,避免了幻读。

间隙锁仅在 RR 隔离级别下出现

PS:在RR(可重复读)的隔离级别下,普通查询是快照读,不会发生幻读。如果使用“当前读”(即:for update)才有可能发生幻读

3.5临键锁(Next-Key Lock)

临键锁:锁住索引本身和索引之前的间隙,左开右闭区间

临键锁的加锁场景:当SQL使用非唯一索引的条件进行数据检索的时候,会给匹配到的行加上临键锁

如下表数据

idnamesexage
1kk10
2lily20
3LiNa30
4QQ40
5HH60
6ZZ80
7NN100

在该表的 age 列增加普通非空唯一索引。
那么临键锁可能的区间为

  • (负无穷, 10] (10, 20] (20, 30] (30, 40] (40, 60] (60, 80] (80, 100] (100, 正无穷)

临键锁的具体产生场景:

  • 如果是等值查询且记录存在,即 begin; select * from xxx where age = 30 for update;
    • 此时仅仅会锁住 age=30 这一行记录
  • 等值查询且记录不存在,即 begin; select * from xxx where agen = 45 for update;
    • 此时会锁住 [40, 60] 的间隙 若 40 <= age <= 60 则会插入失败
  • 范围查询 select * from where age >= 25 and age <=35
    • 首先查询 age = 25 的记录判断是否存在,不存在 临键锁 (20, 30]
    • 同上 age = 35 不存在,加锁 (30, 40]
    • 总加速范围 Next-Key Lock (20, 40]

加锁规律总结

唯一索引等值查询

  • 查询记录存在,记录锁 Record Lock
  • 不存在,间隙锁 Gap Lock

唯一索引范围查询

  • 间隙锁或记录锁

非 唯一索引等值查询

  • 记录存在 Next-key Lock 临键锁 和 间隙锁 Gap Lock
  • 记录不存在 间隙锁 Gap Lock

非 唯一索引范围查询

  • Next-Key Lock 临键锁

3.6插入意向锁

在执行插入一行记录操作之前设置的一种间隙锁。
解决的问题:

  • 多个事务,在同一个索引范围区间内,执行插入操作的时候,如果插入的数据不冲突,就不会阻塞彼此。
  • 假设 数据范围 [7, 100] 多个时候在范围区间内插入不同数据的时候不会阻塞

3.7自增锁

特殊的表级别锁,针对 AUTO_INCREMENT

  • 如果表中新增一条数据,就会持有自增锁
  • 此时其他事务向表中插入数据必须等待自增锁释放,以便保证连续的主键值
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值