题目重点:解释读者看到哪些版本,说明MVCC如何减少读写争用及仍存在的写冲突。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 明确问MVCC基本原理。练习以事务快照、版本可见性和隔离级别讨论;具体transactionId编码、版本存储和回收机制由引擎决定。
- 不能把MVCC等同于serializable,也不能把所有语句都看到同一事务快照视为通用事实。以PostgreSQL作参考时区分语句与事务隔离合同。
解题路线
- 更新生成可见性不同的版本,而不是让并发读者看到半个更新。快照根据事务提交/可见规则选择一个版本;未提交写不是任意读者都可见。
- 语句级snapshot可让同一事务两条查询看到中途提交的数据;repeatable snapshot可保持稳定视图。先问隔离等级,再解释non-repeatable read等现象。
- 减少普通读取与写入的冲突不代表没有lock。两writer改同一对象、DDL或显式锁仍有冲突;write skew也可能在snapshot模型下出现,需要约束/锁/serializable检测。
- 旧版本不能在仍有活跃快照需要它时回收。长事务可能增加历史保留、表膨胀或清理延迟,需观测最老snapshot及事务生命周期;不把清理当随时可删旧数据。
手动走一遍
T1开始稳定快照看到余额10,T2提交余额20,T1按自身快照仍可能读10;新快照可读20。两个医生分别看“另一个仍值班”后各自退出,改不同行也可能违反至少一人值班的约束。
规模与取舍
存储额外成本取决于更新频率、版本宽度和最长保留快照。可见性检查和扫描性能受版本链/索引影响;MVCC不保证任何查询固定O(1)或消除全部锁等待。
易错点与追问
容易失分的边界
- MVCC就没有锁。
- 稳定快照就自动可串行化。
- 长事务未结束时强删它仍需要的旧版本。
继续深挖
- 怎样识别write skew并用业务约束表达?
- 长报表是否应使用只读副本或快照导出,代价是什么?
技术参考
- PostgreSQL MVCC简介:技术语义参考,具体题目按本文约定。
- PostgreSQL隔离级别:技术语义参考,具体题目按本文约定。
