一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

为什么MySQL的意向锁 Intention Lock 能提高加锁效率?

时间:2026-06-20 09:07:58 编辑:袖梨 来源:一聚教程网

意向锁解决表级加锁时避免全表扫描行锁的问题:不加意向锁时LOCK TABLES需检查每行锁状态,引发大量随机I/O;加意向锁后仅需读取表级元数据,IS允许READ表锁、拒绝WRITE,IX拒绝所有表锁。

意向锁解决的是“表级加锁时要不要扫全表行锁”这个问题

不加意向锁时,LOCK TABLES t WRITE 这类语句真会尝试检查每行是否被其他事务加了 X 锁——不是逻辑上必须这么做,而是兼容性兜底逻辑要求它能判断“整张表是否空闲”。对千万行表,这等于触发大量随机 I/O,锁请求本身就会卡住几秒。意向锁把这个问题压缩成一次表级元数据读取:看到 IX 就知道底下肯定有行正被修改,直接拒绝;看到 IS 就知道至少有行被读,WRITE 仍拒绝,但 READ 可放行。

IS 和 IX 锁的触发条件与常见误判点

你写不出 LOCK TABLES ... IN INTENTION MODE 这种语句——意向锁完全由 InnoDB 自动加,但它的出现取决于你执行的语句类型:

  • SELECT ... LOCK IN SHARE MODE → 触发 IS 锁(同时在命中行加 S 锁)
  • INSERTUPDATEDELETESELECT ... FOR UPDATE → 触发 IX 锁(同时在命中行加 X 锁)
  • 没走索引的 UPDATEDELETE → 仍加 IX,但会为全表每行加 X 行锁,效果接近“伪表锁”,此时 IX 是真瓶颈,不是假象

容易错判的是:以为 SELECT 不加锁就不会有意向锁——其实在 REPEATABLE READ 隔离级别下,SELECT ... LOCK IN SHARE MODE 才加 IS;普通 SELECTREAD COMMITTED 下根本不会触发任何意向锁。

意向锁兼容性真正影响的是表锁,不是行锁

很多人查 performance_schema.data_locks 看到一堆 ISIX 就慌,其实它们彼此完全兼容:ISIX 可以共存,多个只读事务或多个更新事务不会因此互相阻塞。真正起作用的兼容规则是:

  • IS 允许 LOCK TABLES t READ,但拒绝 LOCK TABLES t WRITE
  • IX 拒绝所有表级锁:READWRITE 都会被阻塞
  • IX 与行级 S 锁兼容,IS 与行级 X 锁兼容——这才是高并发能成立的基础

DDL(如 ALTER TABLE)被卡住,90% 是因为某个未提交事务持有 IX,而不是因为你写了什么错的 SQL。

监控时只看 data_locks 会漏掉关键信息

SELECT object_schema,object_name,lock_type,lock_mode FROM performance_schema.data_locks WHERE lock_type = 'TABLE' 能看到 ISIX,但这只是“症状”。真正要查的是背后那个事务:

  • SELECT * FROM INFORMATION_SCHEMA.INNODB_TRXTRX_STATE 是否为 RUNNINGLOCK WAIT,再看 TRX_QUERY 是什么语句
  • 如果 TRX_STATE = RUNNINGTRX_STARTED 很久,大概率是应用层没 COMMIT 或网络超时挂住了
  • INNODB_LOCK_WAITS 能告诉你谁在等谁,但前提是等待已发生;而 IX 长期存在却无等待,说明问题不在锁本身,而在事务生命周期管理

意向锁本身从不阻塞任何操作,它只是个标记。看到它长期存在,别优化 SQL,先查事务有没有 commit。

热门栏目