【问题标题】:Atomic conditional update in RethinkDBRethinkDB 中的原子条件更新
【发布时间】:2017-06-08 15:54:14
【问题描述】:

RethinkDB 给了我们一些atomicity guarantees under certain conditions。我正在尝试使用修订字段来利用它来实现乐观并发(c#)。这个想法是,如果在客户编辑自己的修订时数据已被修改,更新应该会失败。应该插入新条目。

var id = "some unique id";
var rev = "the old known revision";
var doc = new {id, Revision = Guid.NewGuid().ToString("N")};
var result = await R.Db("test").Table("table")
    .Get(id)
    .Replace(found => 
        R.Branch(
            found.Eq(null), doc,
            found["Revision"].Eq(rev), doc,
            found
        )
    ).RunResultAsync(connection);

上面的代码似乎可用于此目的,但我想知道它是否确实会消除紧密并发访问的竞争条件。换句话说,这个更新/插入或更新插入是原子的吗?如果可能,请指导我查阅一些文档。

文档提到了一个 check-and-set register(它也可能是 CAS,比较和交换),我认为它对于解释哪些操作实际上是原子的和我们如何保证它(例如使用集成测试)。

我的印象是,如果满足以下条件:

  • write_acks:多数
  • 耐用性:硬
  • read_mode:多数

如果写入不涉及辅助查询或其他文档,则写入是原子的。那些ifs,我喜欢那里有太多的信心。如果有标志或操作必须是原子的,我更愿意,否则核对它。在那之前,我能相信我的印象吗? 还有confusion on SO

【问题讨论】:

    标签: c# concurrency rethinkdb upsert atomic


    【解决方案1】:

    您的示例查询是原子的。它是原子的,因为它使用Replace 修改单个文档。如果它修改了多个文档,则整个查询将不是原子的,但对每个文档的修改将是单独的原子操作。

    ReplacenonAtomic 有一个标志,默认为 true。除非您将nonAtomic 参数传递给Replace,否则传递给Replace 的函数将自动执行。

    没有完整查询 atomicnonAtomic 标志。

    当您尝试以原子方式执行非确定性操作时,RethinkDB 会抛出错误:

    无法证明参数是确定性的。也许你想使用 non_atomic 标志?

    documentation you linked to 提到:

    要在单个原子操作中读取和修改文档,请使用更新或替换命令。

    检查和设置寄存器只是可以原子执行的操作的一个示例。它还用于说明原子操作的注意事项:只有传递给 ReplaceUpdate 的函数是原子的。周围查询不是,例如FilterGetAll

    RethinkDB 操作绝不是跨多个键的原子操作

    阅读discussion you linked to,混淆似乎源于文档中的错误。它曾经说过

    如果用户运行的查询不能原子执行,默认情况下RethinkDB会抛出错误。

    但被更正说

    如果更新或替换查询不能原子执行,默认情况下RethinkDB会抛出错误

    另见How does the atomicity model work?

    每个文档都支持写入原子性——对单个 JSON 文档的更新保证是原子的。 RethinkDB 与其他 NoSQL 系统的不同之处在于,原子文档更新不限于可能操作的一小部分 - 可以对单个文档执行的任何操作组合都保证以原子方式更新文档 .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-07
      • 1970-01-01
      相关资源
      最近更新 更多