mysql存储引擎如何实现行锁_mysql锁机制说明-mysql教程

InnoDB行锁实际锁的是索引记录而非数据行;主键/唯一索引等值查询加记录锁,普通索引等值查询同时锁二级索引和主键,范围查询加间隙锁+记录锁,无索引时退化为近似表锁。

InnoDB 的行锁到底锁的是什么

InnoDB 实现行锁,**不是直接锁住某一行数据本身**,而是通过在索引记录上加锁来实现的。这意味着:如果没有合适的索引,UPDATE 或 DELETE 语句可能退化为表锁(或间隙锁组合),而不是你期望的“只锁一行”。

常见错误现象:SELECT ... FOR UPDATE 在无索引字段上执行后,其他事务更新同表任意行都被阻塞——这说明实际加了表级意向锁+大量记录锁,而非行锁。

  • 主键或唯一索引等值查询(如 WHERE id = 100)→ 加 **记录锁(Record Lock)**
  • 普通索引等值查询 → 同样加记录锁,但会同时在主键上加锁(聚簇索引锁定)
  • 范围查询(如 WHERE age > 25)→ 加 **间隙锁(Gap Lock) + 记录锁**,防止幻读
  • 无索引字段查询 → 优化器可能走全表扫描,对所有扫描到的记录加锁,效果接近表锁

为什么 SELECT FOR UPDATE 有时不生效

行锁只在事务中、且隔离级别 ≥ READ COMMITTED 时才起作用;但如果语句没走索引,或者被 MySQL 优化器判定为不可加锁(比如查询条件含函数、隐式类型转换),SELECT ... FOR UPDATE 可能不加任何行级锁,仅加意向锁。

典型场景:执行 SELECT * FROM user WHERE name = '张三' FOR UPDATE,但 name 字段没建索引 → InnoDB 无法精确定位记录,只能对聚集索引的每条记录尝试加锁,最终可能因锁冲突或死锁检测提前释放,看起来“没锁住”。

  • 检查执行计划:EXPLAIN 确认是否用到索引,type 字段不能是 ALL
  • 避免隐式转换:比如 WHERE mobile = 13800138000(mobile 是 VARCHAR),会导致索引失效
  • 注意隔离级别:READ UNCOMMITTED 和 READ COMMITTED 下不使用间隙锁,但幻读风险上升

REPEATABLE READ 下的间隙锁与死锁风险

MySQL 默认隔离级别 REPEATABLE READ 会启用间隙锁(Gap Lock),它锁住的是索引记录之间的“空隙”,用于阻止其他事务插入新记录,从而解决幻读。但这也带来更高死锁概率。

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » mysql存储引擎如何实现行锁_mysql锁机制说明-mysql教程
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4023260+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4023260+
  • 本周更新: 0+
  • 最后更新: 2026-03-16