事务、ACID 与 BASE
事务怎样把多个操作作为一个工作单元?
- 事务: 把一组数据库操作放入同一提交边界,对外提供规定的成功或失败语义;
- 示例: 转账的扣款和入账应共同成功或共同撤销,否则只完成一侧会破坏余额规则;
- 边界: 单库事务只保护其负责的资源,发邮件、外部扣款等副作用不会自动被数据库回滚;
- 产品条件: 是否支持多记录事务、隔离级别和持久性由数据库与配置决定,不由 SQL/NoSQL 标签决定;
ACID 分别保护什么性质?
| 性质 | 含义 | 常见误解 |
|---|---|---|
| Atomicity 原子性 | 同一事务的修改共同提交或撤销 | 不等于所有外部副作用也可撤销 |
| Consistency 一致性 | 提交前后满足已定义的约束 | 不等于自动保证所有业务规则 |
| Isolation 隔离性 | 限制并发事务互相干扰的程度 | 不同隔离级别并非都等价串行执行 |
| Durability 持久性 | 已确认提交在约定故障模型下保留 | 不等于任何灾难下绝不丢失 |
- 业务责任: 数据库只能执行表达出来的规则,遗漏转账校验或唯一性约束不能靠 ACID 自动补足;
- 隔离选择: 更强隔离可能增加等待或重试,应按实际允许的并发异常选择;
BASE 如何描述放宽即时一致性的系统?
- BASE: 用基本可用、软状态和最终一致性描述一类容忍暂时分歧的系统设计思路;
- 基本可用: 在约定故障下仍尽可能提供服务,业务必须说明哪些功能可以降级;
- 软状态: 不同副本可能暂时不同,状态还会随着异步传播与修复变化;
- 最终一致性: 停止新增写入且通信、修复持续推进后,副本最终收敛,不能仅说“以后总会正确”而没有收敛条件;
- 应用责任: 处理旧读、冲突和重试,并定义用户可理解的中间状态;
- 与 ACID 关系: 二者不是逐项互斥的开关,同一系统可在局部使用 ACID,在跨边界同步时允许最终一致;
最终一致性对业务流程提出什么要求?
- 读取预期: 页面可能暂时看不到刚完成的更新,需要显示处理中、版本状态或明确允许的等待时间;
- 冲突策略: 多个位置并发写入时要有确定的合并或拒绝规则,否则仅传播数据不会自动使业务正确;
- 收敛验证: 停止写入并恢复通信后,检查各副本是否到达同一目标状态,也要观察完成收敛所需时间;
- 选择边界: 对不能容忍超卖或重复占用的关键规则,可在局部事务中保持强约束,而让展示或分析结果异步更新;
事务成功时会经历哪些状态?
Active → Partially committed → Committed → Terminated
- Active: 正在执行读写与校验,事务尚未完成;
- Partially committed: 最后一条业务操作已执行,但提交相关工作还未全部确认;
- Committed: 提交条件满足,修改正式生效,随后可以释放相关资源;
- Terminated: 生命周期结束,不能继续把该事务当作仍可修改的活动事务;
事务失败时怎样恢复?
Active / Partially committed → Failed → Aborted → 终止或重新开始
- Failed: 操作、约束或恢复检查失败,事务不能沿原路径继续提交;
- Aborted: 已撤销该事务的修改,回到符合约定的状态;
- 重试: 可恢复冲突可以启动新事务重试,业务错误应返回明确结果,不能无条件循环;
- 不确定结果: 客户端超时不等于服务器未提交,应通过幂等请求或查询结果避免重复执行;