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 = "把查到的行当场加写锁,直到事务结束" ,用来实现悲观并发控制;务必走索引、尽量短事务、按需设置超时。

相关推荐
提笔了无痕13 小时前
MySQL SQL 从 EXPLAIN 到索引优化,搞懂 SQL 为什么慢
android·sql·mysql
辰同学ovo15 小时前
从一条 SQL 到三个原则:MySQL 心智模型
sql·mysql·adb
Mico1817 小时前
MySQL 8.0.35 GTID主从复制常见管理操作
mysql
网安墨雨18 小时前
MySQL数据库 SQL语句详解
自动化测试·软件测试·数据库·python·sql·mysql
muddjsv19 小时前
SQLite与MySQL/PostgreSQL本质区别:运行模型、并发、部署、权限全方位对比
mysql·postgresql·sqlite
Mico1821 小时前
MySQL 8.0.35 GTID + 延迟复制 + 过滤复制搭建
mysql·dba
会编程的土豆1 天前
结构体 struct:用代码描述用户、订单、座位
数据库·mysql·golang
瞬间&永恒~1 天前
【MySQL】4-6:在同一个主机上使用 systemd 运行多个 MySQL服务器
服务器·数据库·mysql
一嘴一个橘子2 天前
MysqL 哪些情况适合创建索引
mysql
时间的拾荒人2 天前
MySQL C语言连接 - 从入门到实战
android·c语言·mysql