[mysql 学习笔记] - Next-key 锁

三种行锁算法

InnoDB 支持行锁,包含三种行锁算法:

  • Record Lock: 单个记录上的锁;
  • Gap Lock: 间隙锁,它锁住的是一个范围,不包含记录本身;
  • Next-key Lock: 等效于 Record Lock + Gap Lock。

特别注意:InnoDB 行锁是通过 给索引上的索引项加锁来实现的。因此,在执行当前读的sql语句时,一定要记得带上索引条件,否则,mysql 将会执行全表扫描,将整个表锁住。

假设有一张测试表 t:

create table t (a int primary key);
insert into t select 1;
insert into t select 2;
insert into t select 5;

执行 select * from t for update(这里一定要使用 当前读),三种锁算法锁定的记录/范围可以表示为:

注:∞ 不是数学意义上的无穷大,只是 mysql 定义的一个不存在的最大值。

Next-key Lock

InnoDB 默认的事务隔离级别是 可重复读(RR),对于行的查询都是使用的 Next-key Lock 算法,当然,为了提高并发性,在特定的查询中,Next-key Lock 可能降级为 Record Lock 或者 Gap Lock

实际的加锁规则是比较复杂的,而且可能因为版本的不同而有所差异,因此,这里不做深究,可以参考文章(MySQL锁详解),对加锁规则做了详细的介绍以及案例展示。再次强调,加锁规则由于版本不同而存在差异,本人机器安装 mysql 版本是 8.0.18,针对文章里第六节描述的 案例 3 和案例 6 就和本人实测结果不一致。

解决幻读问题

幻读指的是在同一事务下,多次执行同样的读取操作,读到的结果集不一致。而 Next-key 通过对范围加锁就可以解决这个问题。

还是用以上测试表 t,一个事务 T1 执行如下查询:

select * from t where a > 2 for update;

查询会返回 5 这一条记录

此时,如果另一个事务 T2 想要执行插入语句: insert into t select 4,那么

如果没有 Next-key Lock,插入语句将会成功执行,那么事务 T1 再次执行以上查询语句将会返回 4 和 5 两条记录,与第一次返回的结果集不一样,不满足可重复读的事务隔离级别。

如果考虑 Next-key Lock,以上 sql 查询会对 (2,+∞)这个范围加锁,因此事务 T2 插入将会被阻塞,由此避免了幻读问题。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值