[MySQL锁 | 青训营笔记]

134 阅读4分钟

介绍

image-20230318162321433

分类

全局锁:锁定数据库中的所有表

表级锁:每次操作锁住整张表

行级锁:每次锁住对应的行数据

1.全局锁

全局锁就是对整个数据库实例加锁,加锁之后整个数据库只能被读,不能被修改,已经更新操作的事务语句将会被阻塞

最经典的应用就是对全库做备份的时候,必须加上全局锁,去保持数据的完整性

image-20230318163449929

全局加锁的语句

 flush tables with read lock; #加锁
 mysqldump -uroot -p123456 库的名字 > file_name
 unlock tables; #解锁

2.表级锁

每次操作锁住整张表,锁定力度大,发生所冲突的概率最高,并发度最低

2.1表锁

2.1.1表共享读锁(read lock)

一旦某张表加了读锁,那么这张表只可以读,任何人不能写,只能读(会阻塞其他客户端的写操作,只有当锁被释放才能结束阻塞)

2.1.2表独占写锁(wriet lock)

某个客户端对某张表加了一张写锁,那么其他客户端对于这张表不可读也不可写(会被阻塞,直到解锁),加锁的客户端可读可写

2.1.3语法

1.加锁: lock tables 表名 read/write

2.释放锁: unlock tables

2.2元数据锁(mata data lock, MDL)

对表结构的锁,为了避免数据的增删改操作数据库的表结构修改的语句有冲突

数据库会自动的使用这个锁

当我们进行增删改查的时候会自动加MDL读锁(共享锁) ;当我们对表结构进行变更的时候会自动加上MDL写锁(排他锁)

2.3意向锁

我们在开启一个事务或者对表的某个数据加上行锁之后,其他客户端如果想对这个表加上一个表锁,那么他会先一条一条的扫描每一行数据,检查是否被加了行锁,这样效率很低,所以MySQL引入了意向锁

当数据被加了行锁之后,会给整个表加上一个意向锁,其他客户端在加表锁的时候就会先检查有没有意向锁,如果有意向锁,且要添加的表锁与意向锁兼容的话就可以加锁,不兼容就不可以加锁

这时又有一个问题,意向锁有什么类型,怎么个兼容法

2.3.1意向共享锁(IS)

这个锁由语句select...lock in share mode添加

lock in share mode 就是加上行锁,并且加上意向锁

与读锁兼容,与写锁不兼容

2.3.2意向排他锁(IX)

insert、updata、delete、select...for updata添加

与读锁,写锁都不兼容,

意向锁之间不会互斥

以下语句可以查看意向锁及行锁的加锁情况:

 BEGIN;
 SELECT * FROM `user` LOCK IN SHARE MODE;
 ​
 select object_schema, object_name, index_name, lock_type, lock_mode, lock_data from performance_schema.data_locks;
 ​
 # 此时其他客户端可以加读锁,加写锁会被阻塞
 ​
 # 加意向排他锁类似
 # 此时其他客户端加读锁和加写锁会被阻塞

3.行级锁

3.1介绍

每次锁住对应的行数据,粒度最小,发生冲突的概率最低,并发度最高,应用在InnoDB存储引擎中

行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁分三类

  • 行锁:锁定单个行记录的锁,防止update和和delete,在RC,和RR隔离级别下支持
  • 间隙锁:锁住索引记录的间隙,防止其他事务在这个间隙进行insert产生幻读,在RR隔离级别之下都支持

image-20230318195845706

  • 临键锁:行锁和间隙锁的组合,同时防止update,delete,insert,在RR隔离级别下支持

3.2行锁

3.2.1 共享锁(s)

允许一个事务去读一行,防止其他事务获得相同数据集的排他锁

3.2.2 排他锁(x)

允许获得排他锁的事务更新数据,防止其他事务获得共享锁和排他锁

image-20230318200503571

使用不同类型的SQL语句会加不同类型的锁

image-20230318200742602

1.针对唯一索引进行索引时,对已存在的记录进行等职匹配时,将自动优化为行锁

2.InnoDB的行锁是针对索引加的锁,当我们通过没有索引的列的条件检索数据,那么此时行锁就会升级为表锁

此语句可以查看意向锁和行锁的加锁情况

 select object_schema, object_name, index_name, lock_type, lock_mode, lock_data from performance_schema.data_locks;

3.3 间隙锁和临键锁

next-key(临键锁)

image-20230318202441171

间隙锁唯一的目的就是防止其他事务插入间隙,间隙锁可以共存,一个事务的间隙锁不会阻止另一个事务在同一个间隙采用间隙锁