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

相关推荐
云贝贝贝5 分钟前
腾讯云 TDSQL(MySQL 版)运维高频 6 坑:代理路由、读写分离、分片键、监控、PITR
运维·mysql·腾讯云
山岚的运维笔记4 小时前
mysql 专业笔记 -- 第 8 章:使用变量
运维·数据库·笔记·后端·学习·mysql·dba
JavaPub-rodert8 小时前
Redis 和 MySQL 如何保证数据一致性?从业务方案到底层原理完整讲解
数据库·redis·mysql
笑梦无境10 小时前
mysql的安装及配置(3)
数据库·mysql·adb
Gent_倪10 小时前
MySQL分库、分表、分区详解
数据库·mysql
Wang's Blog10 小时前
Vibe Coding一人即团队系列54:云服务器 Node.js 与 MySQL 9 环境搭建及配置指南
服务器·人工智能·mysql·node.js
数智启示录11 小时前
Apache Kafka 幂等 Producer 的边界:Exactly-Once 到了 MySQL 为什么失效 【Kafka合集】
数据库·经验分享·分布式·mysql·面试·kafka·apache
—Miss. Z—11 小时前
计算机三级数据库技术—填空题
数据库·mysql
Gent_倪13 小时前
MySQL 与 Hive 语法异同点详解
数据库·hive·mysql
老周聊架构13 小时前
Flink 连接器与生态:Kafka Offset 提交修复与 MySQL Binlog 延迟指标
mysql·flink·kafka