MySQL 有哪些锁
在MySQL
里,根据加锁的范围,可以分为全局锁、表级锁和行锁三类。
全局锁
使用全局锁,需要执行下条命令:
flush tables with read lock
执行后,整个数据库处于只读状态,,这时其他线程执行以下操作,都会被阻塞:
- 对数据的增删改操作,比如
insert
、delete
、update
等语句; - 对表结构的更改操作,比如
alter table
、drop table
等语句。
如果要释放全局锁,则要执行这条命令:
unlock tables
全局锁的应用场景
全局锁主要应用于做全库逻辑备份,这样在备份数据库期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样。
表级锁
MySQL 里面表级别的锁有这几种:
- 表锁;
- 元数据锁(MDL);
- 意向锁;
- AUTO-INC 锁;
表锁
表锁是最基本的表级锁类型,用于锁定整个表。表锁可以是读锁(共享锁)或写锁(排他锁)。
- 读锁(共享锁):多个事务可以同时获取读锁,但不能获取写锁。
- 写锁(排他锁):只有一个事务可以获取写锁,其他事务不能获取读锁或写锁。
- 示例
-- 获取读锁
LOCK TABLES my_table READ;
-- 获取写锁
LOCK TABLES my_table WRITE;
-- 释放锁
UNLOCK TABLES;
元数据锁(Metadata Lock, MDL)
我们不需要显示的使用MDL
,因为当我们对数据库表进行操作时,会自动给这个表加上 MDL
:
对一张表进行
CRUD
操作时,加的是MDL
读锁对一张表做结构变更操作的时候,加的是
MDL
写锁
MDL
是为了保证当用户对表执行CRUD
操作时,防止其他线程对这个表结构做了变更。
当有线程在执行select
语句( 加MDL
读锁)的期间,如果有其他线程要更改该表的结构( 申请MDL
写锁),那么将会被阻塞,直到执行完select
语句( 释放MDL
读锁)。
反之,当有线程对表结构进行变更( 加MDL
写锁)的期间,如果有其他线程执行了CRUD
操作( 申请MDL
读锁),那么就会被阻塞,直到表结构变更完成( 释放MDL
写锁)。
意向锁
意向锁用于表明一个事务即将对表中的某些行加锁。意向锁分为意向共享锁(IS)
和意向独占锁(IX)
。
在使用
InnoDB
引擎的表里对某些记录加上「共享锁」之前,需要先在表级别加上一个「意向共享锁」;在使用
InnoDB
引擎的表里对某些纪录加上「独占锁」之前,需要先在表级别加上一个「意向独占锁」;
也就是,当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。
而普通的select
是不会加行级锁的,普通的select
语句是利用MVCC
实现一致性读,是无锁的。
意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(lock tables ... read)
和独占表锁(lock tables ... write)
发生冲突。所以,意向锁的目的是为了快速判断表里是否有记录被加锁
AUTO-INC 锁
AUTO-INC
锁用于保护自增列的值。在插入新记录时,InnoDB
会获取AUTO-INC
锁,以确保自增列的值是唯一且连续的。
行级锁
行级锁是数据库管理系统(DBMS)
中最细粒度的锁类型,用于锁定表中的特定行。行级锁允许多个事务同时访问同一张表的不同行,从而提高并发性能。行级锁主要用于解决并发事务中的数据一致性问题。
行级锁的类型主要有三类:
Record Lock
,记录锁,也就是仅仅把一条记录锁上;Gap Lock
,间隙锁,锁定一个范围,但是不包含记录本身;Next-Key Lock
:Record Lock + Gap Lock
的组合,锁定一个范围,并且锁定记录本身。
Record Lock
Record Lock
称为记录锁,锁住的是一条记录。而且记录锁是有共享锁(S 锁,Shared Lock)
和排他锁(X 锁,Exclusive Lock)
之分的:
当一个事务对一条记录加了
S型记录锁
后,其他事务也可以继续对该记录加S型记录锁
(S 型与 S 锁兼容),但是不可以对该记录加X 型记录锁
(S 型与 X 锁不兼容);当一个事务对一条记录加了
X 型记录锁
后,其他事务既不可以对该记录加S 型记录锁
(S 型与 X 锁不兼容),也不可以对该记录加X 型记录锁
(X 型与 X 锁不兼容)。
Gap Lock
Gap Lock
称为间隙锁,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。
间隙锁虽然存在 X 型间隙锁和 S 型间隙锁,但是并没有什么区别,间隙锁之间是兼容的,即两个事务可以同时持有包含共同间隙范围的间隙锁,并不存在互斥关系,因为间隙锁的目的是防止插入幻影记录而提出的
Next-Key Lock
Next-Key Lock
称为临键锁,是Record Lock + Gap Lock
的组合,锁定一个范围,并且锁定记录本身。
next-key lock
是包含间隙锁+记录锁
的,如果一个事务获取了 X 型的 next-key lock
,那么另外一个事务在获取相同范围的X 型的 next-key lock
时,是会被阻塞的
插入意向锁
一个事务在插入一条记录的时候,需要判断插入位置是否已被其他事务加了间隙锁(next-key lock 也包含间隙锁)。
如果有的话,插入操作就会发生阻塞,直到拥有间隙锁的那个事务提交为止(释放间隙锁的时刻),在此期间会生成一个插入意向锁,表明有事务想在某个区间插入新记录,但是现在处于等待状态。