剖析 MySQL InnoDB 共享行锁 (S) & 排他行锁 (X)

MySQL InnoDB 共享行锁(S) & 排他行锁(X)

注意:行锁只在 InnoDB 引擎,并且事务开启下生效;自动提交 autocommit=1 时锁会立刻释放,看不到锁效果 。

行锁是记录锁,锁住某一行数据,不是锁整张表。

1、共享行锁 S(Shared,读锁)

加锁语法 :select ... for share;(MySQL8.0,旧版 LOCK IN SHARE MODE)

  • 特性:
  1. 多个事务可以同时加S锁(读读兼容)
  2. 如果事务A对一行加S锁,其他事务还可以继续加S锁 ,但不能加X排他锁
  3. S锁事务可以读数据;不能修改这行数据,要修改必须升级为X锁

使用场景

  1. 先读取数据,后续业务要修改,希望防止别人把这条数据删掉/做重大修改,但允许别人读取

举例:订单校验,先查询订单状态,后续要更新订单;不希望别的事务直接更新/删除这条订单,但允许其他业务读取订单信息。

sql 复制代码
begin;
select * from t_order where id=100 for share; -- 加S共享行锁
-- 业务逻辑校验
update t_order set status=2 where id=100; -- 尝试修改,S锁升级X锁,如果此时有其他S锁,会阻塞等待
commit;
  1. 多事务共同读取同一行,数据要保证读取期间不被别的事务改写

适合:数据核对、统计,允许多方读,但禁止别人写。

⚠️ S锁坑点:

如果多个事务同时加S锁,然后都想更新这行,互相等待,直接死锁 。

事务1:S锁 → 想升级X锁;事务2:S锁 → 想升级X锁;互相阻塞,死锁。

所以业务要更新的场景,更推荐直接用X锁,不要用S锁。

2、排他行锁 X(Exclusive,写锁)

加锁语法 :select ... for update;

DML语句(update / delete / insert)会自动给命中行加X排他锁。

  • 特性:
  1. 互斥 :一行加了X锁之后,其他事务既不能加S锁,也不能加X锁
  2. 持有X锁的事务,可以读写这行;其他事务读写都会阻塞等待锁释放。

使用场景

  1. 并发更新,防止超卖、数据错乱(最常用)

扣库存:查询库存同时上锁,不允许其他事务修改该行,避免并发超卖

sql 复制代码
begin;
select stock from goods where id=1 for update; -- 加X行锁
update goods set stock = stock -1 where id=1;
commit;
  1. 业务确定接下来就要修改/删除该行,直接上写锁,避免幻读、脏写
  2. delete、update 执行时,InnoDB自动加X行锁,不需要手动写for update。

锁兼容矩阵(重点)

当前持有锁 申请S锁 申请X锁
S锁 ✅ 通过 ❌ 阻塞
X锁 ❌ 阻塞 ❌ 阻塞

对比总结

锁类型 语法 核心特点 适用场景 不适合场景
S共享行锁 select ... for share 允许多个事务读;阻止别人写 多读,短时间校验,允许其他事务读取 后续要更新,多并发更新,容易死锁
X排他行锁 select ... for update/update/delete 独占,别人不能读也不能写 并发修改、扣库存、订单状态变更 大量并发只读场景,会造成大量阻塞

实际业务最佳实践

  1. 绝大多数并发更新场景,直接用 X锁(for update),尽量少用S锁,规避S锁带来的死锁风险。
  2. S锁适合:只做校验读取,确定本事务不会修改该行的场景。
  3. 行锁生效前提:where条件命中索引,如果没走索引,InnoDB会退化成表锁,整张表锁住,性能灾难。
  4. 锁直到事务commit / rollback才释放,事务不要写大业务,尽快提交,减少锁持有时间。

补充区分快照读 vs 当前读

  • 普通select:快照读,不加锁,走MVCC,不受行锁影响,可以读到旧版本数据。
  • for share / for update / update / delete:当前读,会真实加行锁。

举个例子:A事务给一行加X锁;B事务普通select依然可以查到数据(MVCC快照),但B执行select ... for update就会阻塞。

相关推荐
白熊--π4 分钟前
读懂 Meta API 限流:从范围判断到工程优化
大数据·数据库·meta·facebook
Java爱好狂.6 分钟前
Java小白如何三天速通redis?
java·数据库·redis·架构师·分布式锁·java面试·java程序员
菜鸟上路_lbz9 分钟前
金仓数据库V9自增id报错
数据库
Novproxy_Z18 分钟前
账号批量封禁复盘:从日志定位是 IP 关联还是行为指纹关联
网络·数据库·tcp/ip
我喜欢就喜欢24 分钟前
IT疑难杂症诊疗室:从现象到根因的系统排查指南
数据库
其实防守也摸鱼33 分钟前
Codex 下载与本地部署实战指南
linux·服务器·前端·数据库·算法·ai
2603_9547083141 分钟前
如何进一步优化微能网协调控制箱的架构优势
大数据·数据库·人工智能·分布式·架构
瑶山1 小时前
stable-diffusion.cpp 参数全集整理(sd-cli.exe / sd-server.exe)
java·数据库·stable diffusion·参数全集
Pocker_Spades_A1 小时前
一文读懂时序数据库:2026 主流产品全景与六大场景选型(1)
数据库·时序数据库
oradh1 小时前
Oracle 物化视图维护总结(原理+用途+案例)
数据库·oracle