秋招——MySQL补充——MySQL是如何加行级锁

文章目录

引言

  • 在做一些SQL的过程中,总是对于行级锁会出现的一些理解上的问题,就找了一些资料,来补充一下,之前只不过是背过了,但是并不深刻理解。
  • 这里参考的都是小林coding的内容,链接
  • 这里是看了小林coding的内容,然后自己在进行二次消化总结,目录结构基本上是一致的。

正文

什么SQL语句会加行级锁

  • 普通的select语句不加行级锁,快照读,通过MVCC来实现的。

  • 两种类型的锁,分别是共享锁和独占锁

  • 共享锁S:满足读读共享,读写互斥。
  • 独占锁X:满足写写互斥,读写互斥。
查询操作增加对应的行级锁

查询加锁的方式有两种,枷锁的查询语句成为锁定读

S型锁

c 复制代码
select ... lock in share mode;

X型锁

c 复制代码
select ... for update;

注意

  • 加锁的读语句,必须要在一个事务中,因为事务结束了就会自动释放锁。
事务的写法

事务的书写方式!!!这里个东西吧,拼多多就问了,就是会问你实操!

使用start transaction

sql 复制代码
START TRANSACTION;  // 开启一个新事物
//..///不同的SQL语句

selet * from table_a where id = 1 for update;

COMMIT;// 最后事务要提交

使用begin实现事务

sql 复制代码
Begin;  // 开启一个新事物
//..///不同的SQL语句

selet * from table_a where id = 1 for update;

COMMIT;// 最后事务要提交
update和delete修改操作也会增加行级锁
  • 删除和修改操作增加的都是独占型锁X型锁
sql 复制代码
update table colA = x where id = 1;
delete from table where id = 1;

行级锁有哪些种类

  • 记录锁Record Lock

    • 紧紧锁住一条记录
  • 间隙锁Gap Lock

    • 锁定一个范围,但是不包含记录本身
  • Next-key锁

    • 记录锁和间隙锁的组合,锁定一个范围并且锁定记录本身。

不同隔离级别下,锁是不同的

  • 读已提交的情况下,是记录锁
  • 可重复读的情况下,是记录锁和间隙锁(防止幻读)
记录锁
  • 记录锁,同时有共享锁和独占锁,需要自己指定。
  • 默认是独占锁,所以不能对这条记录进行任何操作
sql 复制代码
begin;
select * from table where condition for update;
commit;
间隙锁
  • 用于可重复读隔离级别,是解决幻读问题。

  • 在一定范围内,不再插入其他的数据

  • 间隙锁之间是相互兼容的

  • 不包含自身

Next-Key锁
  • 是记录锁和间隙锁的结合体,锁住一个范围的同时,还锁住了自身。
  • 保护该记录,并且组织其他事务将新纪录插入到被保护的记录前面的间隙中。

不同Next-Key锁之间是互不兼容的

MySQL是如何加行级锁?

  • 加锁的对象是索引,加锁的基本单位是next-key锁,
  • 但是在能够使用记录锁或者间隙锁就能避免幻读的场景
    • next-key锁会退化为记录锁和间隙锁

加锁的对象是针对索引的!!!

唯一索引等值查询
  • 使用唯一索引,进行等值查询的时候,按照查询记录是否存在,将锁退化为两种不同的形态
查询记录是存在的
  • 索引树上定位到这条记录后,将记录中的next-key退化为记录锁

陷入阻塞


退化为记录锁的原因

  • 主键具有唯一性,插入一个同主键的key-value,不满足唯一性约束。
  • 加了记录锁,就无法删除该纪录。
查询记录是不存在的
  • 在查询树上找到第一条大于该查询记录的记录后,将该记录中的next-key锁退化为间隙锁。


确定间隙锁的范围

  • 大于当前搜索的id的最接近的一个值,以当前值右边界,然后前一个值就是左边界。
  • 在唯一索引等值擦查询并且记录不存在的情况下,在索引树找到第一条大于该查询记录的记录后,将该记录的索引next-key退化为间隙锁

使用间隙锁,保证右边界不会被锁,在限定范围内就可以保证不出现幻读

唯一索引范围查找

唯一索引范围查找过程

  • 会对每一个扫描到的索引,加上next-key锁,然后如果遇到下述情况,会退化成记录锁或者间隙锁。
针对大于或者大于等于的范围查询

大于的情况

  • 对两个不同的区域加上next-key锁,限定访问范围
    • 第一个匹配的主键索引上,增加(edge,value]的范围锁,限定在这个范围内不在增加新的数据。
    • 对于最后一个特殊暴击的主键的索引上,就增加一个(value,+∞】主键索引,限定在这个范围内,不在增加的新的数据。

大于等于的情况

  • 在等值索引匹配上,增加了一个记录锁,限定当前的值不被修改。其余都是相同的。

    总结
  • 针对大于等于条件的唯一索引范围查询的情况下,如果条件值得记录存在于表中,该查询是等值擦汗寻,所以该记录锁对应得索引中锁退化为记录锁
针对小于等于的范围查询
  • 第一个数据增加的是next-key锁,限定是(-∞,a]

    • 保证不能在a之前插入数据
  • 后续每一个索引,加的锁都是next-key锁,限定范围是(left_edge,right-edge】

    • 保证上一个匹配到当前匹配之间的范围内,不增加任何新的数据
  • 找到第一个不满足约束条件的索引,当前退化为间隙锁

    • 保证在最后一个匹配的样本,到第一个不匹配的样本的范围内,不会插入新的元素
非唯一索引等值查询
  • 当我们使用非唯一索引进行等值查询的时候,存在两个索引,一个主键索引,还有一个是非唯一索引
    • 加锁的时候,会同时对两个索引都加锁
    • 对主键索引加锁的时候,只有对满足查询条件的记录,才会对主键索引进行加锁。

查询记录存在并且使用的不是唯一索引

非唯一索引等值查询过程

  • 对整个表格进行扫描,直到扫描到第一个不符合条件条件的二级索引记录,就会停止扫描
  • 再扫描过程中,对于的扫描到的二级索引记录增加的是next-key锁,
  • 对于第一个不符合条件的二级索引记录,该二级索引的next-key锁退化为间隙锁,
  • 对于符合查询条件的记录的主键索引加上记录锁。
记录不存的情况
  • 首先会对非唯一索引进行排序,找到第一个不满足等值条件的记录,
    • 二级索引,退化为间隙锁。
  • 能不能插入成功,是需要考虑到二级索引底层结构的实现,首先对二级索引进行排序,然后再具有相同二级索引的记录的主键索引进行排序。
记录存在的时候
  • 加锁过程具体如下
    • 符合条件的记录的主键索引退化成记录锁
    • 二级索引当前锁保持不变
    • 第一个不满足条件的二级索引,退化为间隙锁。
非唯一 索引范围查询
  • 非唯一索引查询,索引的nextkey 不会退化成间隙锁和记录锁的情况,二级索引加的也是next-key锁
    • 满足条件的主键索引仍旧是记录锁


没有加索引的查询
  • 如果锁定读查询语句,没有使用索引列座位查询条件,或者查询语句没有走索引查询,导致扫描是全表扫描的
    • 每一条记录的索引上,都会加next-key锁,锁住全表

不走索引,只要是执行update、delete、for update都是锁住整个表

总结

  • 想想就难受呀,拼多多主管面,就剩下最后一面了,那个主管面,基本上什么都没答出来,很难受,但凡那里看了一遍,我都不至于面试面的那么差,而且很多东西都很基础,我就是忘记了。没注意到这些细节,很难受!
  • 不想了,技不如人,没有准备好,那几天太浪了,没有好好备战,活该吧!后续提前批,要加把劲!
  • 事情蛮多的,这里太细了,不过大概懂了就行了。今晚还得赶着刷两道题,还得写一个党政结课的论文。

所有的加锁还有所退化,都是的为了避免幻读!!

当前读一定要使用索引进行操作,否则就是全表锁住

相关推荐
白菜!!!4 分钟前
SQL INSERT批量插入方式
数据库·sql·mysql·mybatis
不如小布.5 分钟前
MYSQL篇二:数据库的操作
数据库·mysql·oracle
屿小夏.6 分钟前
【SQL】已解决:SQL错误(15048): 数据兼容级别有效值为100、110或120
数据库·sql·oracle
小的~~8 分钟前
大数据面试题之数据库(2)
大数据·数据库
醇氧21 分钟前
【MySQL】MySQL 9.0悄悄的来了
数据库·mysql
毛瞌羊23 分钟前
浅析MySQL-索引篇01
数据库·mysql
丁总学Java1 小时前
MySQL高级-MVCC-原理分析(RR级别)
数据库·mysql·mvcc·rr级别·可重复读
“抚琴”的人1 小时前
C#——Path类详情
开发语言·数据库·microsoft·c#
创作小达人1 小时前
InnoDB中的表级锁、页级锁、行级锁详解
java·数据库·mysql
周杰伦的稻香2 小时前
“LNMP环境搭建实战指南:从零开始配置CentOS 7下的Nginx、MySQL与PHP“
mysql·nginx·centos