由于没有执行 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开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
最后如何让自己一步步成为技术专家
说句实话,如果一个打工人不想提升自己,那便没有工作的意义,毕竟大家也没有到养老的年龄。
当你的技术在一步步贴近阿里p7水平的时候,毫无疑问你的薪资肯定会涨,同时你能学到更多更深的技术,交结到更厉害的大牛。
推荐一份Java架构之路必备的学习笔记,内容相当全面!!!
成年人的世界没有容易二字,前段时间刷抖音看到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。
你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!
进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!
【关注】+【转发】+【点赞】支持我!创作不易!
到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。
你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!
进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!
【关注】+【转发】+【点赞】支持我!创作不易!