面试命中率90%!面试官,java项目面试实操

执行 insert 语句,判断是否有和插入意向锁冲突的锁,如果有,加插入意向锁,进入锁等待;如果没有,直接写数据,不加任何锁;

执行 select … lock in share mode 语句,判断记录上是否存在活跃的事务,如果存在,则为 insert 事务创建一个排他记录锁,并将自己加入到锁等待队列;

MySQL使用间隙锁的目的

=============

间隙锁的主要目的是为了防止幻读,其主要通过两个方面实现这个目的:

  1. 防止间隙内有新数据被插入

  2. 防止已存在的数据,更新成间隙内的数据

另外一方面,是为了满足其恢复和复制的需要。对于基于语句的日志格式的恢复和复制而言,由于MySQL的BINLONG是按照事务提交的先后顺序记录的,因此要正确恢复或者复制数据,就必须满足:在一个事务未提交前,其他并发事务不能插入满足其锁定条件的任何记录,根本原因还是不允许出现幻读。

锁规则

  1. 规则1:加锁的基本单位是临键锁(Next-key Lock)

  2. 规则2:查找过程中访问的对象才会加锁

  3. 优化1:索引上的等值查询,给唯一键加索引的时候,如果查询值存在,临键锁(Next-key Lock)会退化成记录锁(Record Lock);如果查询值不存在,会按照优化2进行优化

  4. 优化2:索引上的等值查询,向右遍历时且最近一个值不满足等值条件时,临键锁(Next-key Lock)会退化成间隙锁(Gap Lock)

  5. bug1:唯一索引上的范围查询会访问到不满足条件的第一个值为止。

在mysql8.0.18及以上已经没有这个bug

锁结构

对不同记录加锁时,如果符合下边这些条件:

  • 在同一个事务中进行加锁操作

  • 被加锁的记录在同一个页面中

  • 加锁的类型是一样的

  • 等待状态是一样的

那么这些记录的锁就可以被放到一个锁结构中。

锁的兼容性

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

从图中可以看出,横向为事务A拥有的锁,竖向为事务B想要获取的锁;举例: 如果前一个事务A 持有 gap 锁 或者 next-key 锁的时候,后一个事务B如果想要持有 Insert Intention 锁的时候会不兼容,出现锁等待。

加锁

==

  1. SELECT … FROM … :InnoDB采用MVCC机制实现非阻塞读,对于普通的 SELECT 语句,InnoDB不加锁。

  2. SELECT … FROM … LOCK In SHARE MODE :显式追加共享锁,InnoDB会使用临键锁(Next-key Lock)进行处理,如果发现了唯一索引,可以降级为记录锁(RecordLock)。

  3. SELECT … FROM … FOR UPDATE :显式追加排它锁,InnoDB会使用Next-Key Lock锁进行处理,如果发现唯一索引,可以降级为RecordLock锁。

  4. UPDATE … WHERE :InnoDB会使用临键锁(Next-key Lock)进行处理,如果扫描发现唯一索引,可以降级为记录锁(RecordLock)。

  5. DELETE … WHERE:InnoDB会使用临键锁(Next-key Lock)进行处理,如果扫描发现唯一索引,可以降级为记录锁(RecordLock)。

  6. insert:InnoDB会在将要插入的那一行设置一个排他的记录锁(RecordLock)。

以 update t1 set name=‘XX’ where id=10 操作为例:

主键加锁

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

加锁行为:仅在id=10的主键索引记录上加X锁。

唯一键加锁

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

加锁行为:先在唯一索引id上加X锁,然后在id=10的主键索引记录上加X锁。

非唯一键加锁

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

加锁行为:对满足id=10条件的记录和主键分别加X锁,然后在(6,c)-(10,b)、(10,b)-(10,d)、(10,d)(11,f)范围分别加Gap Lock。

无索引加锁

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

加锁行为:表里所有行和间隙都会加X锁。(当没有索引时,会导致全表锁定,因为InnoDB引擎 锁机制是基于索引实现的记录锁定)。

锁模拟

===

查看事务、锁的语句:

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

输出结果解析:

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

数据准备:

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

锁举例

锁等待超时:ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

死锁:1213 Deadlock found when trying to get lock

等值查询间隙锁

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

分析:

  1. 由于表T没有 id=7 这条记录,加锁单位是 Next-key Lock ,事务1加锁范围是 (5, 10] ,因为 id=7 是一个等值查询,根据优化规则, id=10 不满足条件, Next-key Lock 退化成 Gap Lock ,因此最终加锁范围是 (5, 10) 。

  2. Session2 想要向这个间隙中插入 id=8 的记录必须等待 Session1 事务提交后才可以。

  3. Session3 想要插入 id=11 ,不在加锁范围,所以可以插入成功。

这是如果有 Session4 想要更新 id=8 的记录,是可以执行成功的,因为间隙锁之间互不冲突;

非唯一键等值锁

=======

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

分析:

  1. Session1 给索引 c 上的 c=5 这一列加上读锁,根据规则1,加锁单位为 Next-key Lock ,因此会给 (0, 5] 区间加上 Next-key Lock

  2. 因为c是普通索引,所以访问 c=5 之后还要向右遍历,直到 c=10 停止,根据规则2访问到的都要加锁,所以加锁范围为 (5, 10] ,根据优化2,等值查询退化为 Gap Lock ,变为 (5, 10),所以最终的加锁范围是 (0, 10);

  3. Session2 想要插入 id=7 的记录,要等待 Session1 提交之后才可以成功插入,因为 Session1 的间隙范围是(5, 10);

  4. 根据原则2,访问到的对象才会加锁,这个查询使用覆盖索引,并不需要访问主键索引,所以主键索引上没有加任何锁。所以 Session3 的语句可以正常执行;

LOCK IN SHARE MODE; 只锁覆盖索引,FOR UPDATE; 会顺便锁上主键索引;

主键索引范围锁

select * from t where id=10 for update;

select * from t where id>=10 and id<11 for update;

对于以上两条SQL,加锁的范围不一致,第一条是id=10 的行锁,第二条是 (10, 15] 的 Next-key Lock。

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

分析:

  1. Session1 根据规则1,加锁单位为 Next-key Lock ,因为 id>=10 是范围查询,直到找到 id=15 停止,最终 Session1 的加锁范围是 (10, 15]

  2. Session3 当去 update 一个存在的值是,给该行添加 Record Lock ,由于 Record Lock 和 Next-key Lock 不兼容,所以阻塞

如果 Session3 更新一个 (10, 15) 的值,则会阻塞;

非唯一索引范围锁

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

分析:

Session1 给索引c加上了 (5,10], (10,15] 两个 Next-key Lock ;由于是范围查询,不触发优化,不会退化成间隙锁

非唯一索引等值锁for Update

数据准备:

面试命中率90%!面试官:你知道MySQL锁吗?5分钟我让他刮目相看

在表t中,a列有普通索引,所以可能锁定的范围有:

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

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

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

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

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

最后

由于细节内容实在太多了,为了不影响文章的观赏性,只截出了一部分知识点大致的介绍一下,每个小节点里面都有更细化的内容!

小编准备了一份Java进阶学习路线图(Xmind)以及来年金三银四必备的一份《Java面试必备指南》

出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频**

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-gw31qN3v-1710438428749)]

最后

由于细节内容实在太多了,为了不影响文章的观赏性,只截出了一部分知识点大致的介绍一下,每个小节点里面都有更细化的内容!

[外链图片转存中…(img-wBNkP5qt-1710438428749)]

小编准备了一份Java进阶学习路线图(Xmind)以及来年金三银四必备的一份《Java面试必备指南》

[外链图片转存中…(img-J42mvros-1710438428750)]

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值