跳到正文

事务、MVCC 与锁 ​

  • 状态:未准备
  • 适用方向:共用 / Go 后端重点
  • 最近复习:待填写
  • 下次复习:待安排

一句话回答 ​

事务保证约定范围内的原子提交与隔离,MVCC 用版本支持一致性读取,锁约束冲突操作;必须先说明数据库、引擎、隔离级别和读写方式。

原理解释 ​

ACID 分别是原子性、一致性、隔离性和持久性;一致性还依赖业务约束和正确的事务代码。数据库事务不会自动覆盖 Redis、HTTP 和消息推送。

以 InnoDB 为例:RC 中普通一致性读通常每条语句建立新快照;默认 RR 通常复用首次一致性读建立的快照,不是一定在 BEGIN 时生成。MVCC 借助记录版本和 undo 支持历史可见性;redo 侧重崩溃恢复,binlog 记录服务层变更,不能混成一个用途。

普通一致性 SELECT 与 SELECT ... FOR UPDATE 等锁定读不同:后者读取并锁定相应记录,不能把旧快照的结论直接套给后续 UPDATE。RR 对范围的锁定读和写入常用 next-key 锁等约束插入,具体范围取决于索引与条件;不要笼统说 MVCC 消除一切幻读。

sql
UPDATE stock SET available = available - 1
WHERE id = ? AND available > 0;

通过受影响行数判断是否扣减成功,避免“先读库存再无条件写”的竞态。若还要创建订单,相关写入放同一事务,并为业务 ID 加约束。

场景与边界 ​

行锁实际与索引访问相关,缺少合适索引可能扩大锁定与扫描范围。死锁可能因不同加锁顺序出现,应用应识别错误并有限重试整个事务;事务中不要夹长耗时网络请求。SQLite 的锁与并发模型不同,不使用这篇的 InnoDB 细节回答 SQLite。

项目中的应用 ​

结合 EinoTalk 落库与推送说明数据库提交不等于消息送达;对照 消息队列一致性讨论跨系统方案。

常见追问 ​

  • RR 完全没有幻读? 需要区分快照读、锁定读与业务流程,不能只背级别表。
  • 提交成功后断网怎么办? 客户端可能不知道结果,重试要靠业务幂等或状态查询。
  • 乐观锁怎么做? WHERE id=? AND version=? 条件更新并递增版本,冲突后明确重试或拒绝策略。

参考资料 ​

理解机制,讲清取舍,用复盘检验掌握。