mysql行锁本质是锁索引,无索引时退化为表锁;间隙锁在rr级别防幻读,唯一等值查询不加间隙锁;死锁由资源访问顺序不一致引发,需统一顺序、缩短事务并重试。

MySQL 锁机制是面试中高频考点,核心不在死记类型,而在理解“为什么这样设计”和“问题发生时怎么定位”。面试官常通过实际场景考察你是否真懂锁的触发条件、作用范围和冲突逻辑。
行锁不是“锁住某一行”,而是“锁住索引记录”
InnoDB 默认加行锁,但本质是加在索引上。如果查询条件没走索引(比如 where name = '张三',而 name 列无索引),就会退化为表锁——全表扫描时对每条记录加锁,等价于锁整张表。即使有索引,也要看是否覆盖:用 SELECT * FROM t WHERE id = 10,主键索引生效,只锁 id=10 这条记录;但若写成 SELECT * FROM t WHERE name = '李四',且 name 是普通索引,那会先锁 name 索引上的匹配项,再回表锁主键记录——两条锁都存在。
- 面试被问“为什么 update 慢还阻塞其他事务?”——先查执行计划,确认是否走了索引;没走,就是隐式表锁
- 想验证是否真加了行锁?可开两个事务,分别 update 不同主键值,不冲突;若 update 同一主键或间隙重叠,第二个会卡住
间隙锁(Gap Lock)防幻读,但只在可重复读(RR)隔离级别生效
RR 下,InnoDB 为防止幻读,在查询范围前后插入位置加上间隙锁。例如 SELECT * FROM t WHERE age BETWEEN 20 AND 30 FOR UPDATE,不仅锁住 age=20~30 的现有记录,还会锁住 (19,20)、(30,31) 这些间隙,禁止其他事务插入 age=21 或 age=25 的新行。但注意:唯一索引等值查询(如 WHERE id = 5)不会加间隙锁,只锁记录本身。
eSiteGroup站群管理系统是基于eFramework低代码开发平台构建,是一款高度灵活、可扩展的智能化站群管理解决方案,全面支持SQL Server、SQLite、MySQL、Oracle等主流数据库,适配企业级高并发、轻量级本地化、云端分布式等多种部署场景。通过可视化建模与模块化设计,系统可实现多站点的快速搭建、跨平台协同管理及数据智能分析,满足政府、企业、教育机构等组织对多站点统一管控的
- 面试常考“为什么 delete 语句卡住了?”——可能是间隙锁冲突,比如事务 A 执行了范围 for update,事务 B 想 insert 一条落在该范围内的新数据,就被间隙锁拦住
- 想绕过间隙锁?改用读已提交(RC)隔离级别(但要接受幻读),或确保查询条件命中唯一索引且是等值匹配
锁升级不存在,但锁数量多会导致性能雪崩
InnoDB 不会把多个行锁自动“升级”为表锁,但如果你 update 时用了 like '%abc' 或没索引的范围条件,可能锁住成千上万行——这时不是锁升级,是锁得太多。锁越多,事务持有时间越长,冲突概率越高,超时风险越大。
- 面试问“如何减少锁竞争?”——优先走覆盖索引、控制事务粒度(避免大事务)、及时提交/回滚、用 select ... for update 前先用 select 确认数据是否存在
- 排查锁等待:查 information_schema.INNODB_TRX 看运行中事务,再联查 INNODB_LOCK_WAITS 和 INNODB_LOCKS 定位谁在等谁、等什么锁
死锁不是 bug,是并发系统的正常现象
MySQL 检测到死锁后,会主动回滚其中代价最小的事务(通常 undo log 少的那个),让另一个继续。死锁日志(show engine innodb status)里能看到两个事务各自持有什么锁、等待什么锁。常见模式:事务 A 先更新 id=1 再更新 id=2,事务 B 反过来先 id=2 后 id=1——只要执行时机交错,就可能死锁。
- 面试被问“如何避免死锁?”——所有事务按相同顺序访问资源(比如固定按主键升序更新)、缩短事务时间、减少锁范围、应用层加重试逻辑
- 不要试图完全消除死锁,重点是让系统能快速发现、安全回滚、业务可重试









