SELECT FOR UPDATE是MySQL中实现悲观锁的重要语句,它会在查询时对选中的行加排他锁(X锁),防止其他事务修改这些数据,直到当前事务结束。
![图片[1]_MySQL中的SELECT FOR UPDATE用法详解_知途无界](https://zhituwujie.com/wp-content/uploads/2025/06/d2b5ca33bd20250613103049.png)
基本语法
SELECT * FROM table_name WHERE condition FOR UPDATE;
主要特性
- 行级锁:只锁定满足条件的行
- 事务范围:锁在事务提交或回滚后自动释放
- 排他性:其他事务不能对这些行加锁或修改
- 阻塞等待:默认会等待锁释放,可设置超时
使用场景
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;
注意事项
- 死锁风险:多个事务按不同顺序锁定资源可能导致死锁
- 性能影响:长时间持有锁会降低系统并发性能
- 索引使用:没有使用索引会导致表锁而非行锁
- 隔离级别:只在REPEATABLE READ和SERIALIZABLE隔离级别下有效
最佳实践
- 尽量缩小锁定范围:只锁定必要的行
- 减少锁定时间:尽快提交或回滚事务
- 统一锁定顺序:避免死锁
- 考虑乐观锁:对于冲突较少的情况,使用版本号可能更高效
与LOCK IN SHARE MODE的区别
| 特性 | FOR UPDATE | LOCK IN SHARE MODE |
|---|---|---|
| 锁类型 | 排他锁(X锁) | 共享锁(S锁) |
| 其他事务 | 不能读(未提交)或写 | 可以读但不能写 |
| 适用场景 | 需要修改数据 | 只读但防止数据修改 |
SELECT FOR UPDATE是处理并发数据一致性的强大工具,但需要谨慎使用以避免性能问题和死锁。
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END

























暂无评论内容