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

相关推荐
万亿少女的梦1685 小时前
基于SpringBoot的考研学习交流系统设计与开发
spring boot·mysql·vue·系统设计·论坛系统
杨云龙UP5 小时前
MySQL基于XtraBackup物理备份搭建GTID主从复制操作手册
数据库·mysql·xtrabackup·主从复制·备份恢复·还原备份文件
我会尽全力 乐观而坚强6 小时前
MySQL库与表的操作
linux·数据库·mysql
lilihuigz6 小时前
产品附加选项插件WooCommerce Product Add-Ons:9种字段类型与3种定价模式提升销售 - 易服客工作室
数据库·mysql·wordpress插件·woocommerce扩展·定制选项
要开心吖ZSH9 小时前
处方物流信息同步优化:从 36 秒到亚秒级的踩坑记录
java·数据库·mysql·性能优化
Sylvia-girl9 小时前
第五站:MySQL常用典型数据类型
数据库·mysql
yoothey10 小时前
MySQL 数据库连接池调优实战
数据库·mysql
Tian_Hang10 小时前
Eclipse Mosquitto 安装及介绍
java·运维·服务器·ide·sql·mysql·eclipse
南墙上的石头1 天前
麒麟 V10 重装人大金仓 V8R6 踩坑实录(含 MySQL 兼容模式)
数据库·mysql
执子手 吹散苍茫茫烟波1 天前
RC 隔离级别下 MySQL InnoDB 死锁典型案例
数据库·mysql