虽然我不能代表 MongoDB 等文档数据库(又名 NoSQL),但我可以告诉您,关系数据库只允许一个 操作 生效。然而,这归结为操作是什么。
例如,假设两个用户试图修改同一个对象。如果他们的修改只修改了列的一个子集,比如说......
用户 1:
update MyTable set Col1 = '1', Col2 = '2' where ID = 'abc'
用户 2:
update MyTable set Col2 = 'x', Col3 = 'y' where ID = 'abc'
您可以确定Col1 将为“1”,而Col3' will be 'y', as those two columns were only updated in one statement. The value ofCol2` 将由最后执行的任何命令确定。
同样,如果一个用户更新了该行而另一个用户删除了它,那么无论如何该行都会被删除。如果更新用户的命令首先出现,则更新将成功,然后将删除该行。如果删除命令先出现,则该行将首先被删除,并且更新不会执行任何操作,因为该行不存在(where 子句不会匹配任何行)。
然而,实际上很少有应用程序会费心使用仅包含已更改列的命令来更新数据库。在几乎所有应用程序中,命令都是在表级别创建的,它们会更新所有列,然后将“当前”(更改或未更改)值传递给这些命令。这就是使用乐观并发的原因。
假设该行 abc 当前具有以下值:
ID = 'abc'
Col1 = '1_original'
Col2 = '2_original'
Col3 = '3_original'
并且两个用户同时检索该行,我们上面的命令看起来更真实:
用户 1:
update MyTable set Col1 = '1', Col2 = '2', Col3 = '3_original' where ID = 'abc'
用户 2:
update MyTable set Col1 = '1_original', Col2 = 'x', Col3 = 'y' where ID = 'abc'
现在我们有一个问题;即使我们的第二个命令真的不关心Col1 中的值,它也可能会覆盖用户1 设置的值。同样,如果用户2 先命中,那么用户1 将覆盖写入Col3 的值由用户 2.
乐观并发本质上扩展了where 子句来检查每个 列的值,而不仅仅是表的键。通过这种方式,您可以确保在检索行和保存行之间的时间段内不会覆盖其他人(或某物)所做的任何更改。
因此,在相同条件下,我们的命令如下所示:
用户 1:
update MyTable set Col1 = '1', Col2 = '2', Col3 = '3_original' where ID = 'abc'
and Col1 = '1_original' and Col2 = '2_original' and Col3 = '3_original'
用户 2:
update MyTable set Col1 = '1_original', Col2 = 'x', Col3 = 'y' where ID = 'abc'
and Col1 = '1_original' and Col2 = '2_original' and Col3 = '3_original'
这意味着最后访问数据库的命令实际上不会做任何事情,因为列将不再具有它们的原始值。