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

5次阅读

全局锁仅适用于离线从库逻辑备份,线上禁用;表级锁分手动锁、MDL、意向锁三类;InnoDB行锁实为临键锁组合,含记录锁与间隙锁;S/X锁是底层语义,可作用于表或行粒度。

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

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

全局锁本质是让整个 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_TRXINNODB_LOCK_WaiTS 才能看清真相。

text=ZqhQzanResources