如何理解InnoDB的行级锁_记录锁与间隙锁Gap Lock的区别
Record Lock锁存在行Gap Lock锁不存在的索引间隙前者为点锁后者为段锁仅在REPEATABLE READ生效Next-Key Lock是其与记录锁组合用于防止幻读。Record Lock 锁的是“存在的行”Gap Lock 锁的是“不存在的空隙”Record Lock记录锁只作用于索引中**真实存在的某一行数据**比如 SELECT * FROM t WHERE id 5 FOR UPDATE就只给 id5 这条记录加锁而 Gap Lock间隙锁锁的是两个索引值之间的**空档区间**比如索引里有 id3 和 id8那 (3, 8) 这个开区间就被锁住——哪怕 id4、id6、id7 这些记录当前根本不存在也不允许其他事务插入。Record Lock 是“点锁”精确到单条索引记录不扩散Gap Lock 是“段锁”范围由索引排序决定和具体数据是否存在无关Gap Lock 只在 REPEATABLE READ 隔离级别下生效READ COMMITTED 下会被自动禁用InnoDB 会退化为仅 Record Lock没有索引的列上执行范围查询InnoDB 会退化为表级锁Gap Lock 失效为什么 UPDATE/DELETE 范围条件会触发 Gap Lock因为 InnoDB 的默认加锁策略是 Next-Key Lock —— 它不是一种独立锁类型而是 Record Lock Gap Lock 的组合行为。只要语句走索引、且是范围扫描比如 WHERE id 10 AND id InnoDB 就会对匹配到的每条记录加 Record Lock同时对每条记录前后的间隙加 Gap Lock。例如索引值为 [5, 10, 15, 25]执行 DELETE FROM t WHERE id BETWEEN 10 AND 20实际锁住的是 (5,10], (10,15], (15,25) 三个区间注意左开右闭重点(15,25) 这个间隙被锁意味着 id18、id22 都不能插入哪怕它们不在 BETWEEN 条件内如果想避免 Gap Lock可改用唯一等值查询如 id 15或临时降级隔离级别但会引入幻读风险常见误判明明没查到数据为什么 INSERT 还被阻塞这就是 Gap Lock 在“静默工作”。比如表里只有 id1 和 id10 两条记录事务 A 执行了 SELECT * FROM t WHERE id 5 FOR UPDATE它虽然没返回任何行但已对 (5,10) 和 (10,∞) 两个间隙加了 Gap Lock此时事务 B 尝试 INSERT INTO t VALUES (7)就会卡住——因为 7 落在 (5,10) 间隙内。Gap Lock 不依赖“查到数据”只依赖“扫描到了哪个索引范围”EXPLAIN 看执行计划能帮你判断是否走索引、是否范围扫描这是预判 Gap Lock 是否触发的关键用 SELECT * FROM performance_schema.data_locks 可实时查看当前持有的锁类型和范围需开启 performance_schema死锁日志里如果出现 lock_mode X locks gap before rec说明就是 Gap Lock 冲突什么时候 Gap Lock 其实没用Gap Lock 不是万能的它只防“插入”不防“更新”或“删除”。比如间隙 (3,8) 被锁别人不能插 id5但若 id5 已存在别人仍可正常 UPDATE ... SET id 5只要没锁该行本身另外主键自增列上的插入不受 Gap Lock 影响因为 InnoDB 对 AUTO_INCREMENT 使用的是专用的 auto-inc lock与 Gap Lock 无关。非唯一辅助索引上的 Gap Lock 可能比主键更“宽”因为相同索引值可能对应多行间隙范围会扩大使用 INSERT ... ON DUPLICATE KEY UPDATE 时先尝试插入若冲突再更新——这个过程可能先申请 Gap Lock再升级为 Record Lock容易引发意想不到的等待线上排查慢 INSERT 时别只盯着目标表要顺藤摸瓜查是否有其他事务正在对同一索引范围做范围 SELECT/UPDATE/DELETEGap Lock 的边界感很弱它不显式声明不报错提示只在你试图插入“不该插的位置”时突然卡住。真正理解它得从索引结构出发而不是从 SQL 表面逻辑猜。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2505084.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!