SELECT ... FOR UPDATE 详解

SELECT … FOR UPDATE 详解

SELECT ... FOR UPDATE 是 SQL 中的一个重要语句,主要用于实现行级锁定机制。下面我将详细介绍它的工作原理和使用场景。

基本概念

SELECT ... FOR UPDATE 是一种悲观锁的实现方式,它会在查询数据的同时对选中的行加上排他锁(exclusive lock),直到当前事务结束(提交或回滚)才会释放。

工作原理

  1. 锁定行为:当执行 SELECT ... FOR UPDATE 时,数据库会锁定满足条件的行,防止其他事务修改或删除这些行
  2. 锁范围:通常锁定的是索引记录,如果没有索引可能会导致表锁
  3. 锁释放:锁会在事务结束时自动释放

基本语法

START TRANSACTION;
SELECT * FROM table_name WHERE condition FOR UPDATE;
-- 执行更新操作
UPDATE table_name SET column = value WHERE condition;
COMMIT;

使用场景

  1. 防止丢失更新:当多个事务同时读取-修改-写入同一数据时
  2. 库存控制:电商系统中防止超卖
  3. 账户余额操作:银行转账等金融操作
  4. 票务系统:座位预订等场景

高级特性

  1. NOWAIT 选项:如果行已被锁定,立即返回错误而不等待

    SELECT * FROM table_name WHERE condition FOR UPDATE NOWAIT;
    
  2. SKIP LOCKED 选项:跳过已被锁定的行

    SELECT * FROM table_name WHERE condition FOR UPDATE SKIP LOCKED;
    
  3. 等待超时:设置锁等待超时时间(MySQL 通过 innodb_lock_wait_timeout 参数)

注意事项

  1. 必须在事务中使用(BEGIN/START TRANSACTION 和 COMMIT/ROLLBACK 之间)
  2. 过度使用可能导致性能问题和死锁
  3. 不同的数据库实现可能有细微差别(MySQL、PostgreSQL、Oracle等)
  4. 在没有合适索引的情况下可能导致表锁

示例

-- 银行转账场景
START TRANSACTION;
-- 锁定源账户
SELECT balance FROM accounts WHERE account_id = 123 FOR UPDATE;
-- 锁定目标账户
SELECT balance FROM accounts WHERE account_id = 456 FOR UPDATE;
-- 执行转账
UPDATE accounts SET balance = balance - 100 WHERE account_id = 123;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 456;
COMMIT;

SELECT ... FOR UPDATE 是处理并发数据修改的强大工具,但需要谨慎使用以避免性能问题。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值