MYSQL - 间隙锁(为什么我想锁单个数据确锁了表?)

2023-06-02  本文已影响0人  意大利大炮

是什么

gap lock间隙锁是指针对索引的范围进行加锁(前开后闭区间)
如下图所示,针对WHERE条件的b=5,在b字段的索引树上加间隙锁:(0-5),(5-10)

image.png

为什么需要间隙锁

当前读和快照读

快照读是指在rr或rc级别下使用mvcc进行select,参考上一篇mvcc的文章。
当前读是直接度数据库记录的值,不管历史版本(undolog)

当前读下幻读问题

在rr级别下,要解决幻读问题。假如没有间隙锁,以下流程会出现幻读问题。
假如有表user,字段:id(primary key),num(普通索引),score。
数据:(1,1,50)

  1. 事务1: 执行select * from user where num>0 for update 结果:查询出id=1得数据
  2. 事务2: 执行insert into user values (2,2,80)
  3. 事务2: 再执行步骤1的语句。结果,返回id=1,2 的两条数据。
    结果,步骤1和3的结果不一致,产生了幻读。

解决

使用间隙锁

索引类型是否会对间隙加锁(不一定加的就是GAP锁)

image.png
image.png

UPDATE

单筛选语句(WHERE条件后面只有一个比较语句)

---- 未完待续 需要补充上一个章实际的范围值

结论:

多筛选语句(WHERE条件里有多个字段)

MySQL会自动选择条件里的一个索引字段进行加锁,优先使用主键、唯一索引,

待补充场景。。。

疑问

疑问一

用户表有num和name两个字段为普通索引字段,更新语句的where条件里有这两个时,另一个事务insert的数据与where条件一致时,会等待name的x,gap锁,但insert数据只有num一样name不一样时,就不等待了,insert数据只有name一样num不一样时又等待了

疑问二

image.png
image.png

针对用户表,进行以下操作:

  1. 事务一:SELECT * FROM user WHERE num = 10 for update;
  2. 事务二:select * from sys.innodb_lock_waits
  3. 查询锁等待情况:select * from sys.innodb_lock_waits
    结果:等待锁的类型是X而不是X,GAP
    image.png
上一篇下一篇

猜你喜欢

热点阅读