高并发下删除和修改的区别
1.并发下删除 如果sn索引为唯一索引
并发执行delete where sn=的时候
事务 1:DELETE deviceId=123 → 加行锁,同时持有「主键索引锁」+「聚簇索引锁」;
事务 2:DELETE deviceId=123 → 先请求「聚簇索引锁」,再请求「主键索引锁」;
若两个事务因「索引锁请求顺序相反」(如事务 1 先锁主键、事务 2 先锁聚簇),仍会形成循环等待 → 死锁。
2.并发下修改 如果sn索引为唯一索引
无循环等待:多个事务并发更新 deviceId=123,仅会「排队等待行锁」(事务 1 释放后事务 2 获取),不会互相持有对方需要的锁;
锁快速释放:UPDATE 仅修改字段,事务日志(undo)量远小于 DELETE,锁持有时间仅毫秒级,几乎无争抢窗口。
当执行DELETE WHERE deviceId=200(deviceId 为普通索引)时,InnoDB 不是「直接锁定目标行」,而是按以下步骤遍历索引并加锁:
索引遍历:从 deviceId 索引的最小值开始,向后扫描直到找到所有 deviceId=200 的行;
加锁规则:对扫描过程中「经过的每一个索引区间」都加 Next-Key Lock(记录锁 + 间隙锁),包括:
目标行所在的区间(如 (100,200]);
目标行之后的下一个间隙(如 (200,300))—— 目的是防止「幻读」(避免其他事务在 200 之后插入新行,导致 DELETE 漏删);
事务 1 等待事务 2 释放 (200,300) 锁的核心原因是:InnoDB 为了防止幻读,要求 DELETE 必须锁定「目标行 + 前后间隙」的所有相关区间;而并发 DELETE 的锁请求顺序反向,导致事务 1 持有 (100,200]、等待 (200,300),事务 2 持有 (200,300)、等待 (100,200],最终形成循环等待(死锁)。
而 UPDATE 通过「精准行锁 + 无间隙锁」规避了这一问题,这也是高并发场景下优先用逻辑删除(UPDATE)的核心原因。
浙公网安备 33010602011771号