mysql 的锁有哪些?
mysql 的锁有哪些?
MySQL 中的锁机制复杂且多样,主要用于控制并发访问,保证数据一致性。根据不同的分类方式,锁可以分为以下几类:
一、按锁的粒度划分
-
全局锁(Global Lock)
- 作用范围:整个数据库实例。
- 功能:锁定所有表,使数据库处于只读状态(除
SELECT、SHOW等读操作外,DML、DDL、事务提交等均会被阻塞)。 - 典型场景:逻辑备份(
FLUSH TABLES WITH READ LOCK),确保备份期间数据一致性。
-
表级锁(Table-level Lock)
- 作用范围:整张表。
- 类型:
- 表共享读锁(Table Read Lock):多个事务可同时读表,写操作被阻塞。
- 表独占写锁(Table Write Lock):仅持有锁的事务可读写表,其他事务读写均被阻塞。
- 特点:开销小、加锁快,并发度低,适用于
MyISAM等非事务引擎(InnoDB也支持,但通常用行级锁)。 - 特殊表锁:
- 意向锁(Intention Lock):
InnoDB为支持行级锁而引入,表明事务稍后会对表中的行加读锁或写锁(分为意向共享锁IS和意向排他锁IX)。 - 自增锁(Auto-inc Lock):插入含自增列(
AUTO_INCREMENT)的表时,MySQL 会锁定自增计数器,保证自增列唯一性(可通过innodb_autoinc_lock_mode调整模式)。
- 意向锁(Intention Lock):
-
行级锁(Row-level Lock)
- 作用范围:表中的单行数据。
- 仅
InnoDB引擎支持,是 MySQL 中粒度最细的锁,并发度最高。 - 类型:
- 共享锁(S Lock,读锁):事务持有后,其他事务可加 S 锁但不可加 X 锁(允许多个事务同时读)。
- 排他锁(X Lock,写锁):事务持有后,其他事务不可加任何锁(仅持有锁的事务可读写)。
二、按锁的功能划分(InnoDB 特有)
-
记录锁(Record Lock)
- 锁定单行记录,防止其他事务修改或删除该记录。
- 例如:
SELECT * FROM t WHERE id=1 FOR UPDATE会对id=1的行加 X 锁。
-
间隙锁(Gap Lock)
- 锁定索引记录之间的间隙(或范围),防止其他事务在间隙中插入新记录,解决幻读问题。
- 仅在
REPEATABLE READ及以上隔离级别生效。 - 例如:
SELECT * FROM t WHERE id BETWEEN 5 AND 10 FOR UPDATE会锁定5~10之间的间隙,阻止插入id=6等新行。
-
临键锁(Next-Key Lock)
- 记录锁 + 间隙锁的组合,锁定记录本身及相邻的间隙,是
InnoDB在REPEATABLE READ级别下的默认行锁算法。 - 例如:索引列有
1,3,5时,锁定3会同时锁定(1,3]范围(包含 3 本身及 1~3 之间的间隙)。
- 记录锁 + 间隙锁的组合,锁定记录本身及相邻的间隙,是
-
插入意向锁(Insert Intention Lock)
- 事务插入数据时,在间隙中预先声明的意向锁,多个事务可在同一间隙插入不同位置的记录,互不阻塞。
- 例如:两个事务同时插入
id=4和id=6到1~7的间隙中,不会冲突。
三、按锁的模式划分
- 乐观锁:假设并发冲突少,不加锁直接操作,提交时通过版本号(如
version字段)或时间戳检查是否冲突(冲突则重试)。实现:UPDATE t SET num=num-1 WHERE id=1 AND version=2(需手动实现)。 - 悲观锁:假设并发冲突多,操作前先加锁(如行级锁、表锁),阻塞其他事务直到释放锁(MySQL 内置的锁多为悲观锁)。
总结
InnoDB主要依赖行级锁(记录锁、间隙锁、临键锁)和意向锁,支持高并发;- 表级锁适用于非事务引擎或简单场景;
- 全局锁用于全库只读操作(如备份)。
实际使用中,需根据业务场景和隔离级别合理设计索引和 SQL,避免死锁和性能问题。