MySQL锁的分类
前言
数据库锁设计的初衷是处理并发问题
根据加锁的范围,MySQL⾥⾯的锁⼤致可以分成全局锁、表级锁和⾏锁三类
目录
前言
全局锁
数据库备份
MySQL官方的备份工具原理
表级锁
表锁
共享锁
排他锁
元数据锁
行级锁
行锁的加锁周期
死锁检测
行级锁类型
行锁
间隙锁
临建锁
意向锁
全局锁
全局锁就是对整个数据库实例加锁
MySQL提供了⼀个加全局读锁的⽅法,让整个数据库处于只读状态。更新、建表、修改表等涉及到数据库变动的语句都会被阻塞
数据库备份
全局锁的最常见使用场景就是做数据库备份
数据库备份加全局锁的原因是一次业务操作可能会是多次增删改查,如果出现一次业务中一半备份上,一半没有备份,数据就混乱了,本质上就是备份系统备份的得到的库不是⼀个逻辑时间点
MySQL官方的备份工具原理
MySQL的事务原理中有读视图,可以记录某一个时间点的数据库版本,然后备份这个时间点的数据库版本,所以可以在备份期间让数据库进行正常操作,MySQL官方的备份工具使用的就是这个原理
表级锁
表锁⼀般是在数据库引擎不⽀持⾏锁的时候才会被⽤到的
MySQL⾥⾯表级别的锁有两种:⼀种是表锁,⼀种是元数据锁
在InnoDB存储引擎中,元数据锁是自动管理的,表锁没有开启,因为会覆盖行级锁
表锁
表锁只作用于数据库表中数据的增删改查
表锁分为共享锁和排他锁两种类型
共享锁
当前线程和其他线程都只能对表中数据进行读取
排他锁
当前线程可以对表中数据进行增删改查,其他线程对表中数据的所有操作都会被禁止
元数据锁
当前线程可以对表结构进行增删改查,其他线程对表结构的所有操作都会被禁止
行级锁
MySQL的⾏锁是在引擎层由各个引擎⾃⼰实现的。但并不是所有的引擎都⽀持⾏锁
在InnoDB存储引擎中,行级锁是默认开启的
行级锁是加在索引上的,没有索引就是全局扫描,取而代之就是表锁
行锁的加锁周期
InnoDB存储引擎支持行锁,在InnoDB事务中,⾏锁是在需要的时候才加上的,但并不是不需要了就⽴刻释放,⽽是 要等到事务结束时才释放。
所以如果你的事务中需要锁多个⾏,要把可能造成锁冲突、昀可能影响并发度的锁尽量往后放
死锁检测
比如事务A在等事务B释放t表的第一行的行锁,事务B在等事务A释放t表的第二行的行锁,在事务中,就形成了MySQL行级死锁,一般MySQL死锁不会当成一个严重的错误,遇到死锁就回滚,业务重试就没事了。
解决方法:
1、设置事务等待超时时间
2、发起死锁检测,发现死锁之后,把其中占据锁资源的事务进行回滚,让它释放出锁资源,让其他事务得以获取锁运行
行级锁类型
行锁
锁定单个行记录的锁
间隙锁
锁定行之间的间隙,防止其他事务在这个间隙进行插入产生幻读
临建锁
行锁+间隙锁,同时锁住数据及数据前面的间隙,左开右闭
意向锁
意向锁分为表级意向锁和行级意向锁,它们类似于所记载的信号灯,快速判断锁冲突,避免全表扫描
数据库会自动添加意向锁或插入意向锁的
其中表级锁中的共享锁和排他锁就有意向锁,行级锁中有插入意向锁
工作原理就是插入这些锁之前,先插入意向锁标记插入意图,冲突就等待或者归滚