介绍

分类
全局锁:锁定数据库中的所有表
表级锁:每次操作锁住整张表
行级锁:每次锁住对应的行数据
1.全局锁
全局锁就是对整个数据库实例加锁,加锁之后整个数据库只能被读,不能被修改,已经更新操作的事务语句将会被阻塞
最经典的应用就是对全库做备份的时候,必须加上全局锁,去保持数据的完整性

全局加锁的语句
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隔离级别之下都支持
- 临键锁:行锁和间隙锁的组合,同时防止update,delete,insert,在RR隔离级别下支持
3.2行锁
3.2.1 共享锁(s)
允许一个事务去读一行,防止其他事务获得相同数据集的排他锁
3.2.2 排他锁(x)
允许获得排他锁的事务更新数据,防止其他事务获得共享锁和排他锁
使用不同类型的SQL语句会加不同类型的锁
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(临键锁)

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