zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

【10.有关锁的面试】

2023-04-18 14:13:02 时间

1. 可重复读下,对于当前读可以加记录锁与间隙锁解决幻读,那此时执行删除指令会不会导致幻读

  • 快照读是通过MVCC方式解决幻读
  • 当前读是通过next-key lock方式解决幻读
  • 事务A通过select * from t_user where age > 20 for update
  • select * from performance_schema.data_locksG;来查询该语句加了什么锁

解释

  • 表里只有一个主键索引, 假设该语句查询到年龄大于 20 岁的用户共有 6 条行记录。此时事务A在主键索引上加了10个next-key(临键锁),锁的范围是(负无穷,正无穷)把整张表锁住了,因此其他事务在对该表进行增、删、改操作的时候都会被阻塞。
  • 或者通过explain会发现type类型为ALL,证明全表扫描

注意

  • 在线上在执行 update、delete、select … for update 等具有加锁性质的语句,一定要检查语句是否走了索引,如果是全表扫描的话,会对每一个索引加 next-key 锁,相当于把整个表锁住了

如果对age字段建立索引

  • 因为表中有两个索引,分别是主键索引和 age 索引,所以会分别对这两个索引加锁。
  • 此时主键id为x型记录锁,age字段锁的范围是从第一个>20的记录到正无穷,所以并不是锁住全表

2. 死锁了怎么办

思索的四个必要条件

  • 死锁的四个必要条件:互斥、占有且等待、不可强占用、循环等待。只要系统发生死锁,这些条件必然成立,但是只要破坏任意一个条件就死锁就不会成立。

在数据库层面,有两种策略通过「打破循环等待条件」来解除死锁状态:

  • 设置事务等待锁的超时时间。当一个事务的等待时间超过该值后,就对这个事务进行回滚,于是锁就释放了,另一个事务就可以继续执行了。在 InnoDB 中,参数 innodb_lock_wait_timeout 是用来设置超时时间的,默认值时 50 秒。
  • 开启主动死锁检测。主动死锁检测在发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑,默认就开启。
  • 回归业务的角度:来预防死锁,对订单做幂等性校验的目的是为了保证不会出现重复的订单,那我们可以直接将 order_no 字段设置为唯一索引列,利用它的唯一性来保证订单表不会出现重复的订单

3. 加了什么锁,导致了死锁?

在这里插入图片描述

  1. 执行完 update t_student set score = 100 where id = 25;然后执行 select * from performance_schema.data_locksG; 这条语句,查看事务 A 此时加了什么锁。

在这里插入图片描述

  • 如果 LOCK_MODE 为 X,说明是 next-key 锁;
  • 如果 LOCK_MODE 为 X, REC_NOT_GAP,说明是记录锁;
  • 如果 LOCK_MODE 为 X, GAP,说明是间隙锁;

因此,此时事务 A 在主键索引(INDEX_NAME : PRIMARY)上加的是间隙锁,锁范围是(20, 30)。

  1. 事务B同上, 在主键索引(INDEX_NAME : PRIMARY)上加的是间隙锁,锁范围是(20, 30)。
  2. 事务Ainsert into t_student(id, no, name, age,score) value (25, 'S0025', 'sony', 28, 90);发现此时多了一个插入意向锁
  3. 事务B insert into t_student(id, no, name, age,score) value (26, 'S0026', 'ace', 28, 90);发现也有一个插入意向锁

在这里插入图片描述

总结:

  • 事务 A 和事务 B 在执行完后 update 语句后都持有范围为(20, 30)的间隙锁,而接下来的插入操作为了获取到插入意向锁,都在等待对方事务的间隙锁释放,于是就造成了循环等待,满足了死锁的四个条件:互斥、占有且等待、不可强占用、循环等待,因此发生了死锁。
  • 间隙锁与间隙锁是兼容的,但是间隙锁与插入意向锁是互斥的
  • 在执行插入语句时,如果插入的记录在其他事务持有间隙锁范围内,插入语句就会被阻塞,因为插入语句在碰到间隙锁时,会生成一个插入意向锁,然后插入意向锁和间隙锁之间是互斥的关系。

文章https://xiaolincoding.com/