Skip to content

MySQL 有哪些锁

MySQL里,根据加锁的范围,可以分为全局锁、表级锁和行锁三类。

全局锁

使用全局锁,需要执行下条命令:

SQL
flush tables with read lock

执行后,整个数据库处于只读状态,,这时其他线程执行以下操作,都会被阻塞:

  • 对数据的增删改操作,比如insertdeleteupdate等语句;
  • 对表结构的更改操作,比如alter tabledrop table等语句。

如果要释放全局锁,则要执行这条命令:

SQL
unlock tables

全局锁的应用场景

全局锁主要应用于做全库逻辑备份,这样在备份数据库期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样。

表级锁

MySQL 里面表级别的锁有这几种:

  • 表锁;
  • 元数据锁(MDL);
  • 意向锁;
  • AUTO-INC 锁;

表锁

表锁是最基本的表级锁类型,用于锁定整个表。表锁可以是读锁(共享锁)或写锁(排他锁)。

  • 读锁(共享锁):多个事务可以同时获取读锁,但不能获取写锁。
  • 写锁(排他锁):只有一个事务可以获取写锁,其他事务不能获取读锁或写锁。
  • 示例
SQL
-- 获取读锁
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 也包含间隙锁)。

如果有的话,插入操作就会发生阻塞,直到拥有间隙锁的那个事务提交为止(释放间隙锁的时刻),在此期间会生成一个插入意向锁,表明有事务想在某个区间插入新记录,但是现在处于等待状态。

如有转载或 CV 的请标注本站原文地址