首页 > mongo的事务一致性如何保持

mongo的事务一致性如何保持

我现在有2个操作,一个insert,一个update,都是对一张表操作的,如何保证事务一致性? upinsert可以多条数据么? mongo官方文档上有Perform Two Phase Commits的文章。除了这个还有其他方案么?


Upsert的意思是没有数据的时候加入一条,那么“多条数据”指的是什么呢?

If set to true, creates a new document when no document matches the query criteria.

回到一致性和这个文章上,中国社区非常给力,官方文档也有中文翻译了!这篇文章是为了模拟出传统数据库中 ACID 里多个操作的 Atomic 和 Consistency。Atomic 指要么操作全都执行,要么都不执行,不能执行一半,改了几条数据了,看哎哟好像不对,那扔着吧。Consistency 在数据库领域的意思跟在分布式系统里的意思不一样,指数据的外部约束有没有满足,比如帐户之间转账,不能最后总和还是负数,或者超过原来的总和了。

那文档中的办法是怎么做的呢?简单说,就是在执行操作之前,记下来要做什么,以后可以 redo。然后保证每个操作都是 幂等的 ,就是说重复执行也没事。比如,赋值是幂等的,但是加一个数就不是幂等的。利用 MongoDB 提供的单文档的原子性,使用一些辅助的数据做到幂等,最后把辅助的数据清除掉。如果你的操作本身就是幂等的,那就不需要辅助数据了。如果要 undo,也是可能的,那就要记下如何 undo。

但是 ACID 中的 Isolation 是没有的,也就是说事务之间有交叉,别的并发操作可以看到中间不一致的状态,上面说的外部约束只能最终得到保证。比如说,事务 T1 包括 (张三:加100;李四:减100),事务 T2 包括 (张三:加200;李四:减200),如果不加以限制,可能的顺序是:

  1. T1 (张三:加100)
  2. T2 (张三:加200)
  3. T2 (李四:减200)
  4. T1 (李四:减100)

T2 执行的时候可以读取并修改 T1 的中间结果,在转账这个问题上没有大问题,因为加减是 可交换 的操作,先后不影响最终结果。但是如果我们把事务改成 T1 (张三 = 100;李四 = 100)T2 (张三 = 200;李四 = 200) 这样最终的结果就可能是 (张三 = 200;李四 = 100),有可能就不满足一致性了。但是如果能在应用里保证顺序地执行这两个事务,问题就避免了。

大家也了解 Isolation 有几个级别,还有多版本等更复杂的。传统数据库在单机上也会在更强的 Isolation 和性能之间做权衡,提供不同的级别可选。这一点在分布式系统中被称作 Consistency,实现起来的代价就更高了,所以 MongoDB 不支持。不过对大多应用,这并不是太大的问题:

  1. 可能异常情况在逻辑上也是可以接受的,比如微信群发,每个人收到的顺序并不一样。
  2. 可能逻辑上并发就是不可能的,比如一个用户只能修改自己的数据,比如只有一个线程写数据。
  3. 或者把需要的数据放到一个文档里,对单文档,MongoDB 保证原子性,别的操作也不可能看到文档一半被改了。
  4. 或者可以在应用上层发现并解决。比如支付宝转账就自己实现了一套一致性协议,1分钟之内可以保证这一笔数据一致了。

对你的要求,如果可以通过修改数据模型,让改动在一个文档里就方便了。最好是看看你具体的需要和应用的假设,分析分析可能出现的异常情况,最后想办法。还有一个办法,贵司可以购买 MongoDB 的支持服务,针对你现在的产品阶段和需求 (开发,维护,咨询,培训),提供不同类型的专业级支持,比再请个程序员 / DevOp / DBA 便宜靠谱多了。我会告诉你他们其实也有中文支持么?

【热门文章】
【热门文章】