很多人学到事务后,以为“有事务就稳了”。
不够。
并发场景里还有一个现实问题:锁冲突。
例如两个窗口同时办理:
窗口 A:先锁市民 1,再准备锁市民 2
窗口 B:先锁市民 2,再准备锁市民 1这就可能死锁。
A 等 B 放
B 等 A 放
=> 死锁MySQL / InnoDB 会检测死锁,并回滚其中一个事务。
这不是数据库坏了,而是数据库在替你打断僵局。
避免死锁最实用的方法有四条:
- 多行、多表更新时保持固定顺序
- 事务尽量短
- 先查清楚,再尽快写完提交
- 不要开着事务等用户点击下一步
还有一个重要认知:
普通 SELECT 不等于加锁读。
在 InnoDB 常见事务场景里,普通读很多时候是快照读;真正要锁行,要明确写 FOR UPDATE 或 FOR SHARE,或者执行会产生锁的写操作。