最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
为什么MySQL的Replace Into语句相比Insert更容易产生锁
时间:2026-07-16 08:16:52 编辑:袖梨 来源:一聚教程网
Replace Into 比 Insert 多加 LOCK_X 记录锁,因其在唯一索引检查阶段即加排他锁,而 Insert 加共享锁;冲突时 Replace Into 不立即释放锁,而是执行删除再插入,导致锁持有时间长、范围广、易死锁。
Replace Into 为什么比 Insert 多加一把 LOCK_X 记录锁
因为 Replace Into 在唯一索引检查阶段就加的是排他锁(LOCK_X),而普通 Insert 加的是共享锁(LOCK_S)。这个差异直接放大了锁冲突概率。
具体来说:当遇到唯一键(UK)冲突时,InnoDB 层在检查 b=8 是否已存在时,Insert 会加 LOCK_S | LOCK_REC_NOT_GAP,允许其他事务并发读;Replace Into 则强制加 LOCK_X,禁止任何其他事务对同一记录加锁——哪怕只是读。
- Insert 检查冲突 → 加
LOCK_S→ 冲突则报错退出,锁很快释放 - Replace Into 检查冲突 → 加
LOCK_X→ 冲突后不立即释放,而是回滚聚集索引插入、再尝试 delete + insert,全程持有该LOCK_X - 如果多个 Replace Into 并发争抢同一个唯一值(如都插
b=8),第一个拿到LOCK_X,其余全卡在等待,极易触发死锁
Replace Into 的两阶段加锁导致锁无法及时释放
Replace Into 不是原子操作,它被拆成「先试插 → 失败 → 再删再插」两个阶段,但第一阶段加的锁不会回退,要等到整个语句执行完才释放。
这意味着:即使你只是想更新一条已存在的记录,MySQL 仍会先尝试插入一条新行(带自增 ID),这个动作会申请插入意向锁(LOCK_INSERT_INTENTION)和间隙锁(LOCK_GAP),而这些锁在冲突发生后并不会立刻释放,而是延续到第二阶段的 delete + insert 完成。
- Session1 执行
replace into t(b) values (8)→ 在b=8上加LOCK_X,同时在(8,100)区间加 next-key 锁 - Session2 同样执行 → 卡在等待
LOCK_X,但它自己也已持有了部分 gap 锁 - 双方互相等待对方释放锁,死锁形成
Replace Into 删除旧记录会触发额外锁类型
Insert 只涉及插入路径,Replace Into 在冲突路径下必须走 delete 流程,这会激活更多锁行为:删除聚集索引行、标记二级索引项、清理 undo log 等,每一步都可能申请新锁。
特别是当表有多个唯一索引时,Replace Into 需要依次检查每个 UK,只要有一个冲突,就可能在多个索引上叠加 LOCK_X;而 Insert 只会在报错前检查一次,且只锁命中索引。
- 有联合唯一索引
UNIQUE KEY (a,b)和单列UNIQUE KEY (c)时,Replace Into 可能同时在两处加LOCK_X - Delete 操作本身会获取聚集索引记录上的
LOCK_X,并可能触发外键检查锁(如果有关联外键) - 自增列(
AUTO_INCREMENT)在 Replace Into 中仍会分配新值(即使最终没用上),受innodb_autoinc_lock_mode影响,可能引入表级锁竞争
Replace Into 在高并发下更容易暴露锁粒度问题
Insert 是纯新增行为,只要不撞唯一键,基本只锁自己那行;Replace Into 的语义本质是「覆盖」,它的锁范围天然更宽——既要防止别人插入相同唯一值(gap lock),又要阻止别人修改或删除当前冲突行(record lock),还要为后续 delete + insert 预留空间(insert intention lock)。
这种组合让 Replace Into 在热点唯一键(比如订单号、设备 ID、用户手机号)场景下,锁等待链极容易拉长。尤其当应用层未控制并发量、又没加重试机制时,一个失败的 Replace Into 可能卡住后续几十个请求。
- 并发量 > 50 QPS 且唯一键重复率 > 20% 时,
Deadlock found when trying to get lock出现频率显著上升 - 使用
INSERT ... ON DUPLICATE KEY UPDATE替代后,同样场景下死锁几乎消失,因为它是原地 update,不触发 delete 阶段的锁扩张 - 若必须用 Replace Into,请确保表只有 1 个唯一索引,并关闭外键、禁用 delete trigger,否则锁路径会进一步复杂化
相关文章
- 王者荣耀世界零氪玩家如何生存 07-28
- 快手极速版怎么绑定手机号 07-28
- 明日方舟和轻松小熊联动活动内容一览 07-28
- 逆战未来黎明之光 逆战未来黎明之光玩法机制与新手入门指南 07-28
- 植物大战僵尸融合版毁灭土豆地雷介绍 07-28
- 逆战未来飓风之龙 逆战未来飓风之龙武器获取方法详解 07-28