我只需要确认我做对了。例如,如果我有一个X
带有字段的实体x
,并且在发送请求时我想做X.x++
。如果我只是使用X = ofy().load().type(X.class).id(xId).get()
然后我会做一些计算,然后我会做X.x++
并保存它。如果在计算期间发布了另一个请求,我会得到一个不需要的行为。X
相反,如果我将在事务中完成这一切,则第二个请求将在我完成之前无法访问。
是这样吗?
对不起,如果这个问题有点笨拙。
谢谢,丹
我只需要确认我做对了。例如,如果我有一个X
带有字段的实体x
,并且在发送请求时我想做X.x++
。如果我只是使用X = ofy().load().type(X.class).id(xId).get()
然后我会做一些计算,然后我会做X.x++
并保存它。如果在计算期间发布了另一个请求,我会得到一个不需要的行为。X
相反,如果我将在事务中完成这一切,则第二个请求将在我完成之前无法访问。
是这样吗?
对不起,如果这个问题有点笨拙。
谢谢,丹
是的,您做对了,但是在使用事务时,请记住完成的第一个获胜,其余的失败。另请查看@Peter Knego 对它们如何工作的回答。
但是,如果第二个请求读取失败,请不要担心。您有 2 个选项:
就重试而言:
可以安全地多次调用您的事务函数,而不会产生不良的副作用。如果这不可能,您可以设置 retries=0,但要知道事务将在第一次发生争用时失败
例子:
@db.transactional(retries=10)
就最终一致性而言:
您可以通过指定请求最终一致性的读取策略来选择退出此保护。通过对实体的最终一致读取,您的应用程序将获取正在读取的实体的当前已知状态,无论是否仍有已提交的更改要应用。对于最终一致的祖先查询,用于查询的索引与从磁盘读取索引的时间一致。换句话说,最终一致性读取策略导致获取和查询表现得好像它们不是当前事务的一部分。在某些情况下,这可能会更快,因为操作不必在返回结果之前等待已提交的更改被写入。
例子:
@db.transactional()
def test():
game_version = db.get(
db.Key.from_path('GameVersion', 1),
read_policy=db.EVENTUAL_CONSISTENCY)
No, GAE transaction do not do locking, they use optimistic concurrency control. You will have access to X
all the time, but when you try to save it in the second transactions it will fail with ConcurrentModificationException
.