MySQL中的锁以及死锁问题

锁的分类
  • 全局锁

​ 要使用全局锁,则要执行这条命令:

flush tables with read lock

执行后,整个数据库就处于只读状态了,这时其他线程执行以下操作,都会被阻塞:

  • 对数据的增删改操作,比如 insert、delete、update等语句;
  • 对表结构的更改操作,比如 alter table、drop table 等语句。

全局锁的应用场景:全局锁主要应用于做全库逻辑备份,这样在备份数据库期间,不会因为数据的更新,而出现备份文件的数据与预期的不一样。

  • 表锁

    1. 意向锁:使用 InnoDB 引擎的表里对某些记录加上「共享锁」之前,需要先在表级别加上一个「意向共享锁」;对某些纪录加上「独占锁」之前,需要先在表级别加上一个「意向独占锁」;意向锁的目的是为了快速判断表里是否有记录被加锁
    2. AUTO-INC 锁在插入数据时,会加一个表级别的 AUTO-INC 锁,然后为被 AUTO_INCREMENT 修饰的字段赋值递增的值,等插入语句执行完成后,就会把 AUTO-INC 锁释放掉。而不是再一个事务提交后才释放。AUTO-INC 锁再对大量数据进行插入的时候,会影响插入性能,因此InnoDB 存储引擎提供了一种轻量级的锁来实现自增。在插入数据的时候,为被 AUTO_INCREMENT 修饰的字段加上轻量级锁,然后给该字段赋值一个自增的值,就把这个轻量级锁释放了,而不需要等待整个插入语句执行完后才释放锁
  • 行级锁

  1. Record Lock(记录锁):也就是仅仅把一条记录锁上;

  2. Gap Lock(间隙锁):锁定一个范围,但是不包含记录本身;

  3. Next-Key Lock(临键锁):Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。

  4. 插入意向锁:一个事务在插入一条记录的时候,需要判断插入位置是否已被其他事务加了间隙锁(next-key lock 也包含间隙锁)。

    如果有的话,插入操作就会发生阻塞,直到拥有间隙锁的那个事务提交为止(释放间隙锁的时刻),在此期间会生成一个插入意向锁,表明有事务想在某个区间插入新记录,但是现在处于等待状态。

MySQL中的死锁

假设表内已经有了6条记录,order_no 字段为非唯一索引:

假设这时有两事务,一个事务要插入订单 1007 ,另外一个事务要插入订单 1008,因为需要对订单做幂等性校验,所以两个事务先要查询该订单是否存在,不存在才插入记录,过程如下:

在这里插入图片描述

事务 A 在执行下面这条语句的时候:

select id from t_order where order_no = 1007 for update;

在二级索引(INDEX_NAME : index_order)上加了 X 型的 next-key 锁,锁范围是(1006, +∞]

由于临键锁可以被两个事务同时取得,所以事务 B在执行下面这条语句的时候:

select id from t_order where order_no = 1008 for update;

事务B也在二级索引(INDEX_NAME : index_order)上加了锁范围为(1006, +∞]X 型的 next-key 锁,而接下来的插入操作为了获取到插入意向锁,都在等待对方事务的间隙锁释放,于是就造成了循环等待,导致死锁

如何避免死锁?

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

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

  • 设置事务等待锁的超时时间。当一个事务的等待时间超过该值后,就对这个事务进行回滚,于是锁就释放了,另一个事务就可以继续执行了。
  • 开启主动死锁检测。主动死锁检测在发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。

业务的角度来预防死锁,对订单做幂等性校验的目的是为了保证不会出现重复的订单,那我们可以直接将 order_no 字段设置为唯一索引列,利用它的唯一性来保证订单表不会出现重复的订单,不过有一点不好的地方就是在我们插入一个已经存在的订单记录时就会抛出异常。

  • 26
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值