关系型数据库模式依赖于原子性多状态事务的存在来确定数据一致性,在将数据库从自相一致的状态迁移到另一状态时,要么组中所有状态都成功,要么所有状态都失败。当尝试将关系型数据库扩展到多个物理服务器上时,由于事务时序使用两段提交协议,该协议将极大地降低哪些跨越多个服务器事务的执行效率。
对于MongoDB来说,由于不允许多文档原子事务,可有效地回避该问题,并采用另一种方法来替代:如何在缺乏事务的情形下维持一致性。
一致性的相关方法
关系型数据库标准化的目标之一是使得原子操作仅仅改变单行数据,以维持数据模型领域级别的一致性。尽管标准化对这样的强制一致性大有帮助,不过仍有些类型的一致性需求无法或难用单个SQL语句来表示,例如:
- 删除一对多关系中的一行数据,应同时也删除那些和该行数据连接的数据。
- 调整订单某行项目的数量后,应该更新订单总费用。
- 银行账户转账时,发送账户的借方和接收账户的贷方应是一个原子操作,要么都成功,要么都失败。另外,其他同时发生的事务部应该看到处于未完成状态的数据。
为了处理类似情形,关系型数据库使用原子多状态事务,此时一组对数据库的更新要么都成功(COMMIT),要么都失败(ROLLBACK)。多状态事务的缺点是使用分布式数据库时事务的执行将变得非常缓慢。然后使用两段式提交协议,可在跨多服务器的分布式数据库中维持一致性。
两段式提交
- 每台服务器准备执行事务,此阶段计算所有更新并保证不导致本服务器内的一致性冲突。
- 一旦所有服务器执行完准备阶段,每台服务器执行作为该事务一部分的更新操作。
两段式提交的缺点在于极大地降低应用的速度,因为每台服务器都需要保证事务可在准备步骤的最后完成,服务器将维持一组对数据的锁定,防止修改。这些锁必须一致维持,直到所有服务器完成准备步骤,这将是一个漫长的过程。
MongoDB设计之初即是面向分布式操作,通过放弃多文档事务的思想来解决该问题。在MongoDB中,每个针对文档的更新都是独立的。