database - Google App Engine 乐观并发

标签 database google-app-engine

我正在阅读 documentation对于 Google App Engine,偶然发现了一些我不太明白的东西:

The Datastore uses optimistic concurrency to manage transactions. When two or more application instances try to change the same entity group at the same time (either by updating existing entities or by creating new ones), the first application to commit its changes will succeed and all others will fail on commit. These other applications can then try their transactions again to apply them to the updated data. Note that because the Datastore works this way, using entity groups limits the number of concurrent writes you can do to any entity in a given group.

这是否意味着如果来自两个不同设备的两个不同用户尝试修改同一个对象,那么只有其中一个会成功?这是典型的数据库行为,还是只是一个 GAE 限制?其他数据库通常如何处理这种情况,即两个或多个用户试图修改同一个对象?

这意味着当两个或多个应用程序实例尝试创建新实体时,只有一个会成功。我理解错了吗?没有两个应用程序实例可以向同一个表添加新对象吗?

最佳答案

虽然我不能代表像 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' 将为“y”,因为这两列仅在一个语句中更新。 Col2` 的值将由最后执行的命令决定。

同样,如果一个用户更新了该行而另一个用户删除了它,那么无论如何都会删除该行。如果更新用户的命令先出现,则更新将成功,然后该行将被删除。如果删除命令先出现,则该行将首先被删除并且更新不会执行任何操作,因为该行不存在(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 会覆盖该值由用户 2 写入 Col3

乐观并发本质上扩展了 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'

这意味着无论哪个命令最后访问数据库实际上都不会执行任何操作,因为列将不再具有它们的原始值。

关于database - Google App Engine 乐观并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10150729/

相关文章:

PHP多重过滤链接

php - 拉取消息线程如何从数据库中列出数据?

jsp - 获取 IllegalStateException : No such servlet: jsp when accessing deployed Spring application to Google App Engine

python - 在 python 中为谷歌应用引擎生成发现文档时找不到模块

java - Google App Engine、JDO、在过滤器中使用日期

php - mysql服务器宕机怎么处理?

php - 如何在php中使id升序

python - 如何将 Python 与数据库一起使用?

google-app-engine - 有没有办法在google flexible appengine中自定义nginx代理

java - Objectify - 如何按 boolean 值过滤?