非ACID RethinkDB或MongoDB如何为不相等的查询维护二级索引

V P*_*V P 13 indexing transactions acid mongodb rethinkdb

这更像是"内部运作"未定问题:

noSQL数据库如何不支持*A*CID(意味着它们无法在单个事务中更新/插入然后回滚多个对象的数据) - 更新二级索引?

我的理解是 - 为了使二级索引保持同步(否则它将变得陈旧) - 这必须在同一事务中发生.

此外,如果索引可能驻留在与数据不同的主机上 - 那么需要存在分布式锁和/或两阶段提交以使这种更新原子地工作.

但是,如果这些数据库不支持多对象事务(这意味着它们不对多个主机上的数据进行两阶段提交),它们使用什么方法来保证驻留在B树结构中的二级索引与数据不陈旧?

cof*_*mug 22

这是一个很好的问题.

RethinkDB始终将二级索引存储在与该表的主索引/数据相同的主机上.即使在连接的情况下,RethinkDB也会将查询带入数据,因此二级索引,主索引和数据始终位于同一节点上.因此,不需要分布式锁定协议,例如两阶段提交.

RethinkDB确实支持一组有限的事务功能 - 单文档事务.原子地记录对单个文档的更改.相关的二级索引更改也会记录为该事务的一部分,因此要么记录整个更改,要么根本不记录任何内容.

扩展有限的事务功能以在单个分片中支持多个文档会很容易,但是跨分片很难做到(因为你提出的分布式锁定原因),所以我们决定不为多个文档实现事务然而.

希望这可以帮助.

  • 澄清一点.表的每个分片都包含分片的所有索引数据.这意味着每个索引的副本与副本一样多.说"记录整个变化,或根本没有记录任何内容"是不正确的.每个副本将记录或不记录更改(以及结果索引更改.)副本,因此其索引可能已过期(并且可以通过传递`use_outdated = True`标志来访问过时数据.此数据将如果没有设置该标志,永远不会被使用,并最终将被更新. (2认同)

Sam*_*aye 3

这是 MongoDB 的答案。

我不太确定你这里的逻辑是什么。更新二级索引与回滚多语句事务(例如多次更新)无关。

MongoDB 每个文档都有事务,这对于更新索引来说很重要。如果需要,可以使用日志反转这些操作。

这必须在同一笔交易中发生。

是的,就像 RDBMS 一样。您应用的索引越多,写入速度就越慢,在我看来您知道原因。

当写入发生时,MongoDB 将使用适用于特定索引的字段更新适用于该集合的所有索引。

此外,索引是否可以与数据驻留在不同的主机上

我不确定 MongoDB 是否允许这样做,我相信有一个 JIRA 可以做到这一点;但是,我目前找不到 JIRA。

那么需要存在分布式锁和/或两阶段提交才能使此类更新以原子方式进行。

最有可能的。允许此功能将是......好吧,我们就说创建一个毛球吧。

即使在分片设置中,每个范围的索引也驻留在分片本身上,而不是配置服务器上。

但是如果这些数据库不支持多对象事务(这意味着它们不跨多个主机对数据进行两阶段提交)

这不是两阶段提交的含义。我相信您需要温习一下两阶段提交是什么:http://docs.mongodb.org/manual/tutorial/perform-two-phase-commits/

我想如果您正在谈论一项涵盖多个分片的交易,那么,嗯,好吧。

他们使用什么方法来保证驻留在与数据分离的 B 树结构中的二级索引不会过时?

我不确定为什么多文档事务会影响索引是否过时,您不跨文档分组。唯一的索引是个例外,但它也适用于单个文档更新;请注意,它的独特性在分片设置中变得有点棘手,并且无法得到保证。

在您创建的索引中,通常每个文档前缀键有一个条目,除非它是文档上的多键索引,否则您可以创建多个索引,但是,无论哪种方式,索引更新都是针对单个对象完成的,而不是由多文档完成交易,我不确定你在这里的逻辑是什么,这就是我给出的答案。