mysql锁有哪些类型_mysql锁分类说明

来源:这里教程网 时间:2026-02-28 20:45:14 作者:

全局锁只在备份时用,但线上千万别直接上

全局锁本质是让整个 MySQL 实例变成只读,命令就是

FLUSH TABLES WITH READ LOCK
。它会阻塞所有 DML(INSERT/UPDATE/DELETE)和 DDL(ALTER/DROP),连事务提交都卡住——不是“慢”,是彻底挂起。

真实场景只适合离线从库做逻辑备份,且必须配合
mysqldump --single-transaction
这类无锁方案优先考虑
主库执行等于停业务;从库执行会堆积 binlog,导致主从延迟飙升 加锁后若客户端异常断开,锁不会自动释放,得靠 DBA 手动
UNLOCK TABLES
或杀连接

表级锁分三类:手动表锁、MDL、意向锁,别混为一谈

表级锁听着简单,实际包含三套完全不同的机制:

LOCK TABLES t1 READ
是 Server 层显式锁,不依赖引擎,MyISAM 和 InnoDB 都认,但业务中几乎不用——它不兼容事务,且会阻塞其他会话的写,甚至阻塞同一会话后续对其他表的写操作
元数据锁(
MDL
)是自动加的,你执行
SELECT
就悄悄持有一个共享 MDL 锁,而
ALTER TABLE
必须等所有 MDL 共享锁释放才能拿到排他锁;常见卡顿就是“查着查着,DDL 一直等”
意向锁(
IS
/
IX
)是 InnoDB 内部用的“预告信号”:比如你要给某行加 X 锁,InnoDB 会先在表上加
IX
锁,这样别的事务想对整张表加表级写锁时,立刻就知道“有人正在动行”,不用逐行检查

行级锁不是一种锁,而是记录锁 + 间隙锁 + 临键锁的组合拳

InnoDB 的“行锁”其实是动态策略:在

REPEATABLE READ
隔离级别下,默认用的是
Next-Key Lock
(临键锁),即记录锁 + 它左边的间隙锁合体。这意味着:

SELECT * FROM users WHERE id = 5 FOR UPDATE
不只锁住 id=5 这一行,还会锁住 (3,5) 这个间隙(假设前一条是 id=3)
SELECT * FROM users WHERE id > 10 FOR UPDATE
会锁住所有 id>10 的记录,以及它们之间的所有间隙,甚至可能锁住“无穷大”之后的插入点
间隙锁(
Gap Lock
)本身不锁记录,只防插入,所以
SELECT ... FOR SHARE
在 RR 级别下也可能触发间隙锁,不是只有
FOR UPDATE
才有

共享锁和排他锁是行为本质,不是独立类型

S 锁
X 锁
是所有锁的底层语义:S 锁允许多个并发读,但会阻塞 X 锁;X 锁是独占的,会阻塞所有 S/X 锁。关键点在于它们可作用于不同粒度:

表级 S 锁 →
LOCK TABLES t1 READ
;表级 X 锁 →
LOCK TABLES t1 WRITE
行级 S 锁 →
SELECT ... LOCK IN SHARE MODE
(MySQL 5.7+)或
SELECT ... FOR SHARE
(8.0+)
行级 X 锁 →
SELECT ... FOR UPDATE
,或任何
UPDATE
/
DELETE
语句隐式持有
注意:
INSERT
不走记录锁,而是先申请
Insert Intention Lock
(插入意向锁),再和间隙锁协调——这也是为什么两个事务同时往同一间隙插不同值,通常不冲突

真正容易被忽略的,是锁的“自动升级”和“隐式持有”:比如一个

UPDATE
没走索引,InnoDB 可能从行锁退化成全表扫描+表级锁;又比如事务里只执行了
SELECT ... FOR UPDATE
却忘了
COMMIT
,那 X 锁就一直挂着,别人一碰那行就卡死。锁不是配置项,是运行时状态,得看
INFORMATION_SCHEMA.INNODB_TRX
INNODB_LOCK_WAITS
才能看清真相。

相关推荐