mongo以单调递增的顺序保存文档

时间:2015-04-27 18:44:26

标签: mongodb

我知道mongo docs提供了一种模拟auto_increment的方法。 http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/

但是MySQL并不能保证并发性。

考虑一系列事件:

  1. 客户端1获得索引1
  2. 客户端2获得索引2
  3. 客户端2使用id = 2
  4. 保存doc
  5. 客户端1保存doc = 1
  6. 的doc

    在这种情况下,可以保存ID小于已保存的当前最大值的doc。对于MySql,由于服务器分配了自动增量ID,因此永远不会发生这种情况。

    如何防止这种情况?一种方法是在每个客户端进行乐观循环,但对于许多客户端,这将导致严重的争用。还有其他更好的办法吗?

    这个用例是为了确保id是“仅向前”。这对于发布许多消息的聊天室以及分页消息很重要,我不希望在前一页中插入新消息。

1 个答案:

答案 0 :(得分:0)

  

但是MySQL并不能保证并发性。

这取决于并发证明的定义,但让我们看看

  

在这种情况下,可以保存ID小于已保存的当前最大值的doc。

这是正确的,但它取决于同时性和单调性的定义。假设您的代码快照系统其他部分的状态,然后获取单调密钥,然后执行可能需要一段时间的插入。在这种情况下,这个明显非单调的插入实际上可能是“更单调”,因为索引2确实在以后捕获,可能反映了一个更近期的状态。换句话说:插入所花费的时间真的很重要吗?

  

对于MySql,由于服务器分配了自动增量ID,因此永远不会发生这种情况。

sounds like folklore。大多数关系型dbs提供对这些功能的细粒度控制,因为严格的保证会严重影响并发性。

MySQL既不保证没有间隙,也不保证在获得较低AUTO_INCREMENT值的事务提交之前,其他读者看不到具有高AUTO_INCREMENT id的事务,除非你保持一个表级锁,严重影响并发性。

对于无间隙,请考虑两个并发插入中的第一个的事务回滚。第二个插入现在是否在提交时分配了新的id?不 - 来自InnoDB documentation

  

如果使用计数器回滚已生成数字的事务,则可能会在分配给AUTO_INCREMENT列的值序列中看到间隙。 (参见14.6.5.5.1结尾,“传统的InnoDB自动增量锁定”)

  

在所有锁定模式(0,1和2)中,如果生成自动增量值的事务回滚,那么这些自动增量值将“丢失”

另外,你完全忽略了复制问题,其中序列导致更多麻烦:

  

因此,在语句结束之前保持的表级锁使得使用自动增量的INSERT语句可以安全地用于基于语句的复制。但是,当多个事务同时执行insert语句时,这些锁限制了并发性和可伸缩性。 (见14.6.5.5.2“可配置的InnoDB自动增量锁定”)

InnoDB行为文档的绝对长度提醒人们在并发系统中做出明显简单的保证的真正复杂性。是的,使用表级锁可以实现插入的单调性,但几乎不可取。如果你采用系统的分布式视图,情况会变得更糟,因为我们甚至无法确定分区模式中的计数器值...