MySQL各存储引擎的锁机制是怎样的?InnoDB等四类引擎详解
MySQL各存储引擎锁机制详解
咱先从日常开发最常用的InnoDB说起,它的锁机制是MySQL里最复杂但也最灵活的,核心是行级锁,能极大提升并发读写性能:
- 基础锁类型:共享锁(S锁,读锁)和排他锁(X锁,写锁)。读操作(比如
SELECT ... LOCK IN SHARE MODE)加S锁,多个事务可以同时持有同一行的S锁;写操作(INSERT/UPDATE/DELETE或SELECT ... FOR UPDATE)加X锁,同一时间只能有一个事务持有某行的X锁,且和S锁互斥。 - 意向锁:为了快速判断表中是否有行锁,InnoDB引入了意向共享锁(IS)和意向排他锁(IX)。当事务要给某行加S锁时,先给表加IS锁;加X锁时先加IX锁。这样其他事务要加表级锁时,不用逐行检查,看表的意向锁就知道有没有冲突。
- 间隙锁&临键锁:在默认的**可重复读(RR)**隔离级别下,InnoDB会用间隙锁(锁定索引之间的空隙)和临键锁(锁定索引行+间隙)来防止幻读。比如执行
SELECT * FROM t WHERE id > 5 FOR UPDATE,不仅会锁定id=5之后的行,还会锁定id=5到下一个存在的id之间的空隙,避免其他事务插入id在这个范围的行。 - 配合MVCC:InnoDB的快照读(普通
SELECT)不会加锁,而是通过多版本并发控制读取历史版本,只有当前读(加锁的SELECT、写操作)才会触发锁机制,这也是它并发性能好的关键。
再聊聊MEMORY引擎,这货是纯内存存储,锁机制走的是简单粗暴的表级锁:
- 读操作加共享表锁,多个事务可以同时读;写操作加排他表锁,同一时间只能有一个事务写。读锁和写锁互斥,写锁之间也互斥。
- 因为内存操作本身速度极快,表级锁的开销可以忽略,所以MEMORY没做行级锁——毕竟没必要为了一点点并发复杂度增加额外开销。不过这也意味着高并发写场景下,MEMORY的性能会大打折扣,因为写操作会阻塞所有其他读写。
至于MERGE引擎,其实它更像个“逻辑表壳子”,本身不实现锁机制,完全依赖底层的MyISAM表:
- MERGE是把多个结构相同的MyISAM表合并成一个逻辑表,对MERGE表的操作最终都会映射到底层的MyISAM表。
- 比如执行查询时,会给所有底层MyISAM表加读锁;执行插入时,会根据MERGE表定义的规则(比如按某个字段分区)找到对应的MyISAM表,给它加写锁。锁的行为完全和MyISAM一致,毕竟只是个“代理”而已。
最后是老牌的MyISAM,它的锁机制是纯粹的表级锁,也是很多老系统的“痛点”:
- 读锁(共享锁):多个事务可以同时持有,互不干扰,适合读多写少的场景。
- 写锁(排他锁):同一时间只能有一个事务持有,和读锁、其他写锁都互斥。
- 自动加锁:MyISAM会自动给操作加锁,比如普通
SELECT加读锁,INSERT/UPDATE/DELETE加写锁;你也可以手动用LOCK TABLES t READ/WRITE来显式加锁。 - 并发插入优化:如果MyISAM表没有“空洞”(没有被删除的行,即表末尾是连续的),那么即使表被加了读锁,其他事务也可以在表末尾插入数据——这是MyISAM为了提升并发做的小优化,但局限性很大。
内容的提问来源于stack exchange,提问作者Lora D.
相关产品推荐
相关产品推荐

