第 19 / 22 篇

附录 A:练习解题方向

本附录提供判断依据。实际结果仍应由对应版本的真实数据库实验确认,不能把书里的预期字符串当成运行记录。

事务与快照

第 1 章:某些 DDL 会触发隐式提交,最后的 ROLLBACK 无法据此撤销已经提交的业务变化。迁移与业务事务应分开,由迁移流程管理版本、权限、锁和回退。

第 2 章:可以将库存分成可用、已预留和已确认消耗,并保存有效入库、退款与释放关系。取消预留时,应在同一事务中改变预留状态和相应库存;外部通知可以通过同事务事件表交付,但仍需处理投递重复。

第 3 章:普通 RR 一致性读的快照不一定在 BEGIN 就建立。先明确有没有此前的一致性读、显式一致性快照或自身修改,再推导可见版本。随书实验证明 BEGIN 后提交的新值可在第一次普通读中看见。

第 4 章:队列认领允许暂时跳过被其他工作者占用的行,随后还需继续轮询和处理遗留任务。财务总额通常不能容忍悄悄遗漏一部分应付款,因此不能因 SKIP LOCKED 返回得快,就将结果当成完整统计。

执行与竞争

第 5 章:检查连接池等待、数据库锁等待、返回数据量、网络与应用处理耗时。为每个阶段分别计时,并以实际连接、事务或请求标识关联。访问路径合理只说明其中一部分工作。

第 6 章:Sleep 表示当前没有执行语句,不表示没有未结束事务。应核对事务起点、此前写入、持有锁与业务归属;终止前确认回滚影响、恢复方式和操作权限。

第 7 章:通知位于数据库事务之外,受害事务回滚无法撤销通知。可把待通知事件与业务变化共同写入数据库,再由发布者处理;发布者和消费者仍需以稳定身份去重。

第 8 章:默认锁等待超时只回滚失败语句,先前写入可能仍在事务里。业务代码应明确局部或整体回滚策略;连接归还边界应避免泄露未提交事务和会话设置。不能只在日志里记录异常便继续使用连接。

身份与恢复

第 9 章:同键不同参数应按合同拒绝冲突,或进入明确的修改操作,不能直接沿用第一次结果。保存规范化后的请求指纹与结果身份,有助于判定重复与冲突。

第 10 章:客户端没有确认不等于数据库没有提交;从库暂时没有记录不等于主库永远没有提交。应保留原键和 unknown,选择可信读取位置与核查方式,在证据不足时限制新执行。

第 11 章:发送后、标记前退出可能导致重复发送。需要稳定事件 ID、发布尝试与确认记录,消费者把去重与业务变化共同提交。一个 sent 布尔值难以表达尝试过程、确认丢失与待核查状态。

第 12 章:重启暂时解除症状,仍可能是连接泄漏、长事务、热点锁或应用线程阻塞。提前采集连接池、事务与等待关系、错误阶段及请求耗时,才能检验这些假设。

实验与交付

实验章中改变配置后,应先写出新的预期,再实际运行。关闭死锁检测、开启 timeout 整事务回滚或更换隔离级别,会改变测试前提,不应只是修改断言来让测试通过。

提交响应丢失实验要同时取得服务器 OK 被故障代理观察到、客户端发生错误、独立连接查到原业务键三份证据。只在客户端手工抛异常,不能证明制造了相同窗口。

第 16 章:业务账号按业务表和操作授权,诊断账号按观测需求授权;创建数据库与全实例信息不应成为所有应用连接的默认权限。备份恢复、高可用与容量等保证应有对应真实演练,本书没有替它们给出通过结论。

第 17 章:设计应逐项映射业务身份、事务边界、数据库约束、错误与恢复。一个有效报告可以坦诚写出“数据库侧 Outbox 已验证,Broker 投递尚未实现”,同时提供继续验证需要的故障窗口。不能用笼统的“全部成功”掩盖不同范围。