MYSQL锁–后面附上的链接是相关的具体介绍
MySQL锁
前言
mysql学习很久了,但是对于mysql中的锁机制以及锁的方式类型还是有很多的不了解,下面是听了关于詹哥的课的分享。
一、mysql锁的分类
- 按照锁的粒度来说,mysql主要包含三种类型(级别)的锁定机制。
1、全局锁:锁的是整个数据库(database),由mysql的SQL layer层(mysql的逻辑架构)实现的。
2、表级锁:锁的是某个table,由mysql的sql layer层实现的。
3、行级锁:锁的是某行数据,也可能锁定行之间的间隙。由某些存储引擎实现
- 按照锁的功能来分:可以分为共享锁与排他锁
- 共享锁(Shared Locks)S锁
1、兼容性:加了S锁的记录,允许其他事务再加S锁,不允许其他事务再加X锁
2、加锁方式:select....lock in share mode
- 排他锁(Exclusive Locks)X锁
1、兼容性:加了X锁的记录,不允许其他事务再加S锁或者X锁
2、加锁方式:select....for update
二、各种锁的详解
2.1全局锁
- 全局锁就是对于整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的MDL的写的语句,DDL语句已经更新的操作的事务提交语句都将被阻塞。其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。
- 加全局锁的命令为
mysql>
flush tables with read lock;
- 释放全局锁的命令为如下:也可以断开session的连接,自动释放全局锁
mysql>
unlock tables
- 说到全局锁用于备份这个事情,是比较危险的。因为如果在主库上加上全局锁,则整个数据库将不能写入,备份期间影响业务运行,如果在从库上加全局锁,则会导致不能执行主库同步过来的操作,造成主从延迟。
- 对于innodb这种支持事务的引擎,使用mysqldump备份时可以使用–single-transaction参数,利用mvcc提供一致性视图,而不使用全局锁,不会影响业务的正常运行。而对于有mylSAM这种不支持事务的表,就只能通过全局锁获得一致性视图,对应的mysqldump参数为 --lock–all–tables。
2.2mysql表级锁
- mysql的表级锁有四种
1、表读锁
2、表写锁
3、元数据锁 (meta data lock,MDL)
4、自增锁(AUTO-INC locks)
2.2.1表读/写锁
- 表读写锁就像名称一样的锁,控制着读和写的锁。
2.2.2元数据锁
- MDL不需要显式使用,在访问一个表的时候会被自动加上。MDL的作用是,保证读写的正确性。你可以想象一下,如果一个查询正在遍历一个表中的数据,而执行期间另一个线程对这个表结构做变更,删了一列,那么查询线程拿到的结果跟表结构对不上,肯定是不行的。
- 因此,在 MySQL 5.5 版本中引入了 MDL,当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。
- 读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。
- 读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行
2.2.3自增锁(AUTO-INC Locks)
- AUTO-INC锁是一种特殊的表级锁,发生涉及AUTO_INCREMENT列的事务性插入操作时产生。
2.3、MySQL行级锁
2.3.1行级锁介绍
- MySQL的行级锁,是由存储引擎来实现的,这里我们主要讲解InnoDB的行级锁。
- InnoDB行锁是通过给索引上的索引项加锁来实现的,因此InnoDB这种行锁实现特点意味着:只有通过索引条件检索的数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
- InnoDB的行级锁,按照锁定范围来说,分为四种:
1、记录锁(Record Locks):锁定索引中一条记录。
2、 间隙锁(Gap Locks):要么锁住索引记录中间的值,要么锁住第一个索引记录前面的值或者最后一个索引记 录后面的值。
3、 临键锁(Next-Key Locks):是索引记录上的记录锁和在索引记录之前的间隙锁的组合(间隙锁+记录 锁)。
4、 插入意向锁(Insert IntentionLocks):做insert操作时添加的对记录id的锁
- innoDB的行级锁,按照功能来说,分为两种:
共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和
2.3.2意向锁 Intention Locks
- InnoDB也实现了表级锁,也就是意向锁,意向锁是mysql内部使用的,不需要用户干预。意向锁和行锁可以共存,意向锁的主要作用是为了【全表更新数据】时的性能提升。否则在全表更新数据时,需要先检索该范是否某些记录上面有行锁。
- 表明“某个事务正在某些行持有了锁、或该事务准备去持有锁”
- 意向锁的存在是为了协调行锁和表锁的关系,支持多粒度(表锁与行锁)的锁并存,。
- 例子:事务A修改user表的记录r,会给记录r上一把行级的排他锁(X),同时会给user表上一把
意向排他锁(IX),这时事务B要给user表上一个表级的排他锁就会被阻塞。意向锁通过这种方式
实现了行锁和表锁共存且满足事务隔离性的要求。- 1)意向共享锁(IS锁):事务在请求S锁前,要先获得IS锁 。2)意向排他锁(IX锁):事务在请求X锁前,要先获得IX锁
- 意向锁的作用
当我们需要加一个排他锁时,需要根据意向锁去判断表中有没有数据行被锁定(行锁)
(1)如果意向锁是行锁,则需要遍历每一行数据去确认;
(2)如果意向锁是表锁,则只需要判断一次即可知道有没数据行被锁定,提升性能。
- 注意:上了行级X锁后,行级X锁不会因为有别的事务上了IX而堵塞,一个mysql是允许多个行级X锁同时存在的,只要他们不是针对相同的数据行。
2.3.3记录锁(Record Locks)
- 记录锁, 仅仅锁住索引记录的一行,在单条索引记录上加锁。
- record lock锁住的永远是索引,而非记录本身,即使该表上没有任何索引,那么innodb会在后台创建一个隐藏的聚集主键索引,那么锁住的就是这个隐藏的聚集主键索引。所以说当一条sql没有走任何索引时,那么将会在每一条聚合索引后面加X锁,这个类似于表锁,但原理上和表锁应该是完全不同的。
-- 加记录共享锁
select * from t1_simple where id = 1 lock in share mode;
-- 加记录排它锁
select * from t1_simple where id = 1 for update;
2.3.4间隙锁(Gap Locks)
- 区间锁, 仅仅锁住一个索引区间(开区间,不包括双端端点)
- 在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身。
- 间隙锁可用于防止幻读,保证索引间的不会被插入数据
2.3.5临键锁(Next-Key Locks)
- record lock + gap lock, 左开右闭区间,例如(5,8]。
- 默认情况下,innodb使用next-key locks来锁定记录。select … for update
- 但当查询的索引含有唯一属性的时候,Next-Key Lock 会进行优化,将其降级为Record Lock,即
仅锁住索引本身,不是范围。 - Next-Key Lock在不同的场景中会退化:
2.3.6插入意向锁(Insert Intention Locks)
(1)插入意向锁是一种Gap锁,不是意向锁,在insert操作时产生。
(2)在多事务同时写入不同数据至同一索引间隙的时候,并不需要等待其他事务完成,不会发生锁等待。
(3)假设有一个记录索引包含键值4和7,不同的事务分别插入5和6,每个事务都会产生一个加在4-7
之间的插入意向锁,获取在插入行上的排它锁,但是不会被互相锁住,因为数据行并不冲突。
(4)插入意向锁不会阻止任何锁,对于插入的记录会持有一个记录锁。
2.3.7行锁加锁规则
- 主键索引
- 等值查询
(1)命中记录,加记录锁。
(2)未命中记录,加间隙锁。- 范围查询
(1)没有命中任何一条记录时,加间隙锁。
(2)命中1条或者多条,包含where条件的临键区间,加临键锁
- 辅助索引
- 等值查询
(1)命中记录,命中记录的辅助索引项+主键索引项加记录锁,辅助索引项两侧加间隙锁。
(2)未命中记录,加间隙锁- 范围查询
(1)没有命中任何一条记录时,加间隙锁。
(2)命中1条或者多条,包含where条件的临键区间加临键锁。命中记录的id索引项加记录锁。
三、相关文档(自己看)
- 1.全面了解mysql锁机制(InnoDB)与问题排查
https://juejin.cn/post/6844903668571963406
- 2.MySQL 三万字精华总结 + 面试100 问,和面试官扯皮绰绰有余(收藏系列)
https://juejin.cn/post/6850037271233331208
总结
上面主要讲的是mysql几个锁的概念,用来自己想看的时候随时可以看不需要自己去查看相关文档。下面是自己看的文档地址:
1.全面了解mysql锁机制(InnoDB)与问题排查 https://juejin.cn/post/6844903668571963406
2.MySQL 三万字精华总结 + 面试100 问,和面试官扯皮绰绰有余(收藏系列) https://juejin.cn/post/6850037271233331208