MySQL的UPDATE默认加行级锁,具体为记录锁、间隙锁或临键锁,取决于WHERE条件是否命中索引、是否唯一及隔离级别。
UPDATE 语句默认加什么锁?
MySQL 的 UPDATE 在 InnoDB 引擎下默认走行级锁,但具体锁类型取决于 WHERE 条件是否命中索引、是否唯一、以及隔离级别。没索引的 WHERE 会升级为表锁;主键或唯一索引等值查询只锁匹配行;范围查询(如 WHERE id > 100)会加间隙锁(Gap Lock)或临键锁(Next-Key Lock),防止幻读。
为什么 UPDATE 会卡住甚至死锁?
常见原因有三类:
- 两个事务交叉更新同一组行,顺序不一致(比如事务 A 先改
id=1再改id=2,事务 B 反过来) - UPDATE 带子查询且子查询扫描大量未索引数据,持有锁时间过长
- WHERE 条件没走索引,InnoDB 退化成全表扫描+表级意向锁,阻塞其他 DML
死锁发生后,InnoDB 会自动选一个事务回滚(报错 Deadlock found when trying to get lock),另一个继续执行。
怎么避免 UPDATE 并发冲突?
核心思路是缩短锁持有时间 + 明确锁粒度: