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

相关推荐
Fleshy数模6 小时前
CentOS7 安装配置 MySQL5.7 完整教程(本地虚拟机学习版)
linux·mysql·centos
az44yao7 小时前
mysql 创建事件 每天17点执行一个存储过程
mysql
秦老师Q8 小时前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
橘子139 小时前
MySQL用户管理(十三)
数据库·mysql
Dxy12393102169 小时前
MySQL如何加唯一索引
android·数据库·mysql
我真的是大笨蛋9 小时前
深度解析InnoDB如何保障Buffer与磁盘数据一致性
java·数据库·sql·mysql·性能优化
怣509 小时前
MySQL数据检索入门:从零开始学SELECT查询
数据库·mysql
人道领域10 小时前
javaWeb从入门到进阶(SpringBoot事务管理及AOP)
java·数据库·mysql
千寻技术帮10 小时前
10404_基于Web的校园网络安全防御系统
网络·mysql·安全·web安全·springboot
spencer_tseng11 小时前
MySQL table backup
mysql