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);
上面的代码似乎可以用于此目的,但我想知道它是否确实会消除紧密并发访问的竞争条件。换句话说,这是更新/插入还是upsert原子?如果可能的话,请指导我一些文件。
文档中提到检查和设置寄存器(也可能是CAS,比较和交换),我认为这对于解释哪些操作实际上是原子和我们如何保证它(例如使用集成测试)。
我认为如果符合以下条件:
如果写入不涉及辅助查询或其他文档,则写入是原子的。那里有太多的信心,我喜欢那些ifs。我更喜欢如果有一个标志或某个东西,操作必须是原子的,否则核武器。那么在那之前,我能相信自己的印象吗? 还有confusion on SO。
答案 0 :(得分:3)
您的示例查询是原子的。它是原子的,因为它使用Replace
修改单个文档。如果它修改了多个文档,整个查询将不是原子的,但对每个文档的修改将是单独的原子操作。
Replace
,nonAtomic
有一个标记,默认为true。除非您将nonAtomic
参数传递给Replace
,否则传递给Replace
的函数将以原子方式执行。
没有完整查询atomic
或nonAtomic
标记。
当您尝试以原子方式执行非确定性操作时,RethinkDB将抛出错误:
无法证明论证的确定性。也许你想使用non_atomic标志?
documentation you linked to提及:
要在单个原子操作中读取和修改文档,请使用更新或替换命令。
检查和设置寄存器只是可以原子方式执行的操作的示例。它还用于说明原子操作的注意事项:只传递给Replace
或Update
的函数是原子的。周围的查询不是,例如Filter
或GetAll
。
RethinkDB操作在多个键上绝不是原子的
阅读discussion you linked to,混淆似乎源于文档中的错误。它曾经说过
如果
用户运行的查询无法原子执行,默认情况下RethinkDB会抛出错误。
但更正说
如果无法以原子方式执行更新或替换查询,默认情况下RethinkDB会抛出错误
另见How does the atomicity model work?
基于每个文档支持写入原子性 - 保证单个JSON文档的更新是原子的。 RethinkDB与其他NoSQL系统的不同之处在于原子文档更新不仅限于可能操作的一小部分 - 可以在单个文档上执行的任何操作组合都可以保证以原子方式更新文档