小林和小周同时读取余额 100,各自准备扣 80。如果都按旧值计算并写回 20,就丢失了一次扣款。锁的任务不是“让数据库变慢”,而是在会破坏业务约束的操作之间建立先后顺序。
START TRANSACTION; SELECT balance FROM accounts WHERE id=7 FOR UPDATE; UPDATE accounts SET balance=balance-80 WHERE id=7 AND balance>=80; COMMIT;
先分清:普通
SELECT 多数时候走 MVCC 快照;FOR UPDATE 和写语句读取当前状态并加锁。锁是否精确,首先取决于查询实际扫描的索引范围。