图文实例解析,InnoDB 存储引擎中行锁的三种算法,2024新一波程序员跳槽季

由于没有执行 commit,所以这个时候事务 T1 没有释放锁,并且锁住了 id = 1 的记录行,此时再来执行事务 2 申请 id = 2 的记录行:

可以看见,由于锁住的是不同的记录行,所以两个记录锁并没有相互排斥,来看一下现在表中的数据,由于事务 1 还没有 commit,所以应该是只有 id = 2 的 username 被修改了:

nice,果然。再执行下事务 1 的 commit,id = 1 的 username 也就被修改过来啦。

行锁退化为表锁示例

再来看下没有使用索引的例子:

同样的,新建两个事务,先执行事务 T1 的前两行,也就是不要执行 commit。我们试图使用 select ... for update 给 username = “user_three” 的记录行加上记录锁,但是由于 username 并非主键也并非索引,所以实际上这里事务 T1 锁住的是整张表:

由于没有执行 commit,所以这个时候事务 T1 没有释放锁,并且锁住了整张表。此时再来执行事务 2 试图申请 id = 5 的记录锁,你会发现事务 T2 会卡住,最后超时关闭事务:

两条不同记录拥有相同的索引,会发生锁冲突吗?

这个问题的答案应该很简单吧,上面我们强调过,行锁锁住的是索引,而不是一条记录(只不过我们平常这么说锁住了哪条记录,比较好理解罢了)。所以如果两个事务分别操作的两条不同记录拥有相同的索引,某个事务会因为行锁被另一个事务占用而发生等待

Gap Lock 间隙锁


这里我先简单提一嘴,下文会详细解释:不同于 Record Lock 是基于唯一索引的,Gap Lock 和 Next-Key Lock 都是基于非唯一索引的。

并且,不同于 Record Lock 锁定的是某一个索引记录,Gap Lock 和 Next-Key Lock 锁定的都是一段范围内的索引记录:

select * from test where id between 1 and 10 for update;

对于上述 SQL 语句,所有在(1,10)区间内(左开右开)的记录行都会被 Gap Lock 锁住,所有 id 为 2、3、4、5、6、7、8、9 的数据行的插入会被阻塞,但是 1 和 10 两条被操作的索引记录并不会被锁住

注意!这里指的是锁住所有的(1,10)区间内的 id,也就是说即使某个 id 目前并不在我们的表中比如 id = 6 ,如果你想插入一条 id = 6 的新纪录,那对不起,不行。

Next-Key Lock 临键锁


Next-Key Lock 是结合了 Gap Lock 和 Record Lock 的一种锁定算法,其主要目的是为了解决幻读问题

例如一个索引有 10,11,13 和 20 这四个值,分别对这个 4 个索引进行加锁操作,那么这四个操作分别对应的 Next-Key Lock 锁住的区间是:

  • (-∞, 10]

  • (10, 11]

  • (11, 13]

  • (13, 20]

  • (20, +∞]

细心的同学应该已经注意到了,和 Gap Lock 的不同之处就在于,Next-Key Lock 锁定的区间是左开右闭的,也就是说它是包含当前被操作的索引记录的。

在 InnoDB 默认的隔离级别 REPEATABLE-READ 下,行锁默认使用的算法就是 Next-Key Lock。但是,如果操作的索引是唯一索引或主键,InnoDB 会对 Next-Key Lock 进行优化,将其降级为 Record Lock,即仅锁住索引本身,而不是范围。

由于主键也是一种唯一索引,所以我们可以这么说:Record Lock 是基于唯一索引的,而 Next-Key Lock 是基于非唯一索引的

需要注意的,当操作的索引为非唯一索引时,InnoDB 会先用 Record Lock 锁住对应的唯一索引,再用 Next-Key Lock 和 Gap Lock 对这个非唯一索引进行处理,而不仅仅是锁住这个非唯一索引。具体地我们举个例子来看下。

Next-Key Lock 示例

假设我们为上面 test 表中新增一个字段,并设置为非唯一索引:

CREATE TABLE test (

id int(11) NOT NULL AUTO_INCREMENT,

username varchar(255) DEFAULT NULL,

class int(11) NOT NULL,

PRIMARY KEY (id),

KEY index_class (class) USING BTREE COMMENT ‘非唯一索引’

) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

插入一些数据:

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

最后如何让自己一步步成为技术专家

说句实话,如果一个打工人不想提升自己,那便没有工作的意义,毕竟大家也没有到养老的年龄。

当你的技术在一步步贴近阿里p7水平的时候,毫无疑问你的薪资肯定会涨,同时你能学到更多更深的技术,交结到更厉害的大牛。

推荐一份Java架构之路必备的学习笔记,内容相当全面!!!

成年人的世界没有容易二字,前段时间刷抖音看到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。

你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!

进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!

【关注】+【转发】+【点赞】支持我!创作不易!

到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。

你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!

进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!

【关注】+【转发】+【点赞】支持我!创作不易!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值