SELECT FOR UPDATE 是怎么使用的?

SELECT ... FOR UPDATEInnoDB 提供的行级排他锁 语法,用来在事务内 把"查到的行"锁住,防止其他事务同时改或删,实现悲观锁流程。


1. 最基本用法

sql 复制代码
START TRANSACTION;

SELECT balance
FROM account
WHERE id = 100
FOR UPDATE;          -- 给 id=100 这一行加排他锁(X锁)

-- 业务逻辑:判断、计算、更新
UPDATE account
SET balance = balance - 100
WHERE id = 100;

COMMIT;              -- 锁自动释放
  • 锁范围命中索引 时是行锁无索引 退化为间隙锁表锁 → 注意覆盖索引/主键
  • 持有时间 :从语句执行成功直到事务提交/回滚

2. 多行/范围锁定

sql 复制代码
-- 锁住余额小于 0 的所有账户(范围锁)
SELECT id
FROM account
WHERE balance < 0
FOR UPDATE;

其他事务无法插入/更新/删除 balance < 0 的行,直到本事务结束。


3. 与 LOCK IN SHARE MODE 区别

锁类型 语法 作用 并发
排他锁 FOR UPDATE 读写都阻塞 悲观写
共享锁 LOCK IN SHARE MODE 读允许,写阻塞 悲观读

4. 超时控制

sql 复制代码
-- 等 3 秒拿不到锁就报错(InnoDB 5.7+)
SELECT ... FOR UPDATE NOWAIT;     -- 立即报错
SELECT ... FOR UPDATE SKIP LOCKED; -- 跳过已锁行,返回空结果
SELECT ... FOR UPDATE WAIT 3;     -- 等待 3 秒(MySQL 8.0)

5. 常见坑

  • 无索引 → 退化为表锁间隙锁 → 并发骤降
  • 长事务 → 锁持有时间长 → 阻塞/死锁概率飙升
  • 快照读REPEATABLE READ)下,FOR UPDATE升级成当前读 ,可能产生幻读 → 需要范围锁/间隙锁

一句话记忆

SELECT ... FOR UPDATE = "把查到的行当场加写锁,直到事务结束" ,用来实现悲观并发控制;务必走索引、尽量短事务、按需设置超时。

相关推荐
原来是猿15 小时前
MySQL【用户管理】
数据库·mysql
sthnyph18 小时前
初识MySQL · 库的操作
数据库·mysql
原来是猿18 小时前
MySQL【视图】
数据库·mysql
2401_8735878218 小时前
MySQL——事务管理
数据库·mysql
0xDevNull19 小时前
MySQL 三大日志系统深度解析:Binlog、Redo Log、Undo Log
数据库·mysql
Java面试题总结19 小时前
htop安装不了怎么解决
mysql
钰衡大师19 小时前
MySQL 数据库备份方案
数据库·mysql
原来是猿20 小时前
MySQL【事务下】
数据库·mysql·oracle
奕成则成21 小时前
面试被问:MySQL 与 Doris/SelectDB 的架构区别。 大数据为什么禁止select *。
mysql·面试·架构
gjc59221 小时前
踩坑实录:MySQL服务器CPU爆高,元凶竟是SELinux的setroubleshootd?
运维·服务器·数据库·mysql·adb