MySQL中的SELECT FOR UPDATE用法详解

SELECT FOR UPDATE是MySQL中实现悲观锁的重要语句,它会在查询时对选中的行加排他锁(X锁),防止其他事务修改这些数据,直到当前事务结束。

图片[1]_MySQL中的SELECT FOR UPDATE用法详解_知途无界

基本语法

SELECT * FROM table_name WHERE condition FOR UPDATE;

主要特性

  1. 行级锁:只锁定满足条件的行
  2. 事务范围:锁在事务提交或回滚后自动释放
  3. 排他性:其他事务不能对这些行加锁或修改
  4. 阻塞等待:默认会等待锁释放,可设置超时

使用场景

1. 防止并发修改

START TRANSACTION;
-- 锁定账户记录
SELECT * FROM accounts WHERE account_id = 123 FOR UPDATE;
-- 执行余额操作
UPDATE accounts SET balance = balance - 100 WHERE account_id = 123;
COMMIT;

2. 实现分布式锁

-- 获取分布式锁
START TRANSACTION;
SELECT * FROM distributed_lock WHERE lock_name = 'order_processing' FOR UPDATE;
-- 执行业务逻辑
COMMIT;

高级用法

1. 设置锁等待超时

SET innodb_lock_wait_timeout = 10; -- 设置锁等待超时为10秒
SELECT * FROM orders WHERE order_id = 456 FOR UPDATE;

2. 跳过锁等待(MySQL 8.0+)

SELECT * FROM products WHERE product_id = 789 FOR UPDATE NOWAIT;
-- 或者
SELECT * FROM products WHERE product_id = 789 FOR UPDATE SKIP LOCKED;

3. 锁定特定索引

-- 强制使用特定索引加锁
SELECT * FROM users FORCE INDEX(primary) WHERE user_id = 101 FOR UPDATE;

注意事项

  1. 死锁风险:多个事务按不同顺序锁定资源可能导致死锁
  2. 性能影响:长时间持有锁会降低系统并发性能
  3. 索引使用:没有使用索引会导致表锁而非行锁
  4. 隔离级别:只在REPEATABLE READ和SERIALIZABLE隔离级别下有效

最佳实践

  1. 尽量缩小锁定范围:只锁定必要的行
  2. 减少锁定时间:尽快提交或回滚事务
  3. 统一锁定顺序:避免死锁
  4. 考虑乐观锁:对于冲突较少的情况,使用版本号可能更高效

与LOCK IN SHARE MODE的区别

特性FOR UPDATELOCK IN SHARE MODE
锁类型排他锁(X锁)共享锁(S锁)
其他事务不能读(未提交)或写可以读但不能写
适用场景需要修改数据只读但防止数据修改

SELECT FOR UPDATE是处理并发数据一致性的强大工具,但需要谨慎使用以避免性能问题和死锁。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞41 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容