关于java:面试官问我一条update语句加了多少锁我总结了全套八股文

48次阅读

共计 1922 个字符,预计需要花费 5 分钟才能阅读完成。

题目:面试官问我一条 updat 语句加了多少锁?我总结了全套八股文

迎面走来了你的面试官,身穿格子衫,挺着啤酒肚,发际线重大后移的中年男子。
手拿泡着枸杞的保温杯,胳膊夹着 MacBook,MacBook 上还贴着公司标语:“我爱加班”。

面试开始,直入正题。

面试官: 看你简历下面写着精通 MySQL,我问你一个 MySQL 锁相干的问题,你看一下这条 SQL 会对哪些数据加锁?

update user set name='一灯' where age=5;

表构造是这样的:

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `age` int DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`),
  KEY `idx_age` (`age`)
) ENGINE=InnoDB COMMENT='用户表';

我: age 是非唯一性索引,MySQL 的锁是加在索引下面的,应该只会对 age=10 的数据加锁。

面试官: 确定吗?

我: 嗯 …,应该是的。

面试官:【讥嘲】,这就是你精通 MySQL 的程度吗?明天面试就先到这里吧,前面有音讯会被动分割你。

前面还可能有音讯吗?你们啥时候被动分割过我?
实话实说的被拒,八股文背得溜反而被录取。
好吧,等我看看一灯怎么总结的 MySQL 的八股文。

我: 这条 SQL 具体对哪些数据加锁,还须要看表中有哪些数据。

MySQL 有三种类型的行锁:

记录锁(Record Locks):

即对某条记录加锁。

# 对 id= 1 的用户加锁
update user set age=age+1 where id=1;

间隙锁(Gap Locks):

即对某个范畴加锁,然而不蕴含范畴的临界数据。

# 对 id 大于 1 并且小于 10 的用户加锁
update user set age=age+1 where id>1 and id<10;

下面 SQL 的加锁范畴是 (1,10)。

临键锁(Next-Key Locks):

由记录锁和间隙锁组成,既蕴含记录自身又蕴含范畴,左开右闭区间。

# 对 id 大于 1 并且小于等于 10 的用户加锁
update user set age=age+1 where id>1 and id<=10;

如果表中只有这样两条数据的话:

id name age
1 张三 1
10 李四 10

针对 age 索引,很产生这样三个索引范畴:

(-∞,1],(1,10],(10,+∞)

方才的这条 SQL:

update user set name='一灯' where age=5;

因为表中不存在 age= 5 的记录,并且 age= 5 刚好落在 (1,10] 的区间范畴内,所以会对 (1,10] 的范畴加锁。

咱们能够用理论数据测试一下:

当咱们执行 update 语句的时候,age= 2 和 age= 8 的数据范畴都被加锁了。

面试官: 小伙子答复的不错啊。如果曾经存在 age= 5 的数据,方才的那条 update 语句会对哪些数据加锁?

我: 如果表中数据是这样的。

id name age
1 张三 1
5 一灯架构 5
10 李四 10

针对 age 索引,很产生这样四个索引范畴:

(-∞,1],(1,5],(5,10],(10,+∞)

方才的这条 SQL:

update user set name='一灯' where age=5;

age= 5 的数据落在 (1,5] 的区间范畴内,所以会对 (1,5] 的范畴加锁。

你认为这就完了吗?MySQL 锁为了保证数据的安全性,还会向右遍历到不满足条件为止,还会再加一个间隙锁,也就是 (5,10] 的范畴。

所以,这条 SQL 的加锁返回是 (1,5](5,10]

跟方才 age= 5 不存在的加锁范畴 (1,10] 是一样的。不信能够再用方才的测试用例跑一遍。

面试官: 小伙子有点货色。如果我把 SQL 中 where 条件换成主键 ID,加锁范畴是什么样的?

update user set name='一灯' where id=5;

我: 因为锁是加在索引下面的。

如果不存在 id= 5 的数据,加锁范畴跟上条 SQL 是一样的,(1,10]

如果存在 id= 5 的数据,MySQL 的 Next-Key Locks 会进化成 Record Locks,也就是只在 id= 5 的这一行记录上加锁。

面试官: 小伙子,降级加薪的机会就是留给你这样的人。薪资 double,今天就来下班吧。

知识点总结:

  1. MySQL 锁是加在索引记录下面的。
  2. 如果是非唯一性索引,不管表中是否存在该记录,除了会对该记录所在范畴加锁,还会向右遍历到不满足条件的范畴进行加锁。
  3. 如果是惟一索引,如果表中存在该记录,只对该行记录加锁。如果表中不存在该记录,除了会对该记录所在范畴加锁,还会向右遍历到不满足条件的范畴进行加锁。

文章继续更新,能够微信搜一搜「一灯架构」第一工夫浏览更多技术干货。

正文完
 0