GAE 交易:传递实体还是密钥?

GAE transactions: pass entity or key?

在使用 GAE 进行交易时,可以传递实体,或者您应该始终将密钥传递给实体。例如,假设我正在将资金从一个实体转移到另一个实体。我应该这样做吗:

@ndb.transactional(xg=True)
def transfer_money(key1, key2, amount):
    entity1 = key1.get()
    entity2 = key2.get()
    entity1.money -= amount
    entity2.money += amount
    ndb.put_multi([entity1, entity2])

或者这样可以吗:

@ndb.transactional(xg=True)
def transfer_money(entity1, entity2, amount):
    entity1.money -= amount
    entity2.money += amount
    ndb.put_multi([entity1, entity2])

还是取决于其他因素?

AFAIK #2 不起作用(事务性),您需要加载(并放入)事务中的对象。

第二个例子没有产生预期的结果。实体是在事务之外检索的,因此 money 中的任何一个在写回之前可能已经更改,并且可能被错误的值覆盖。

这个特殊情况也是使用 tasklets 的一个很好的例子。

@ndb.transactional_tasklet(xg=True)
def transfer_money(key1, key2, amount):
    entity1, entity2 = yield key1.get_async(), key2.get_async() # parallel
    entity1.money -= amount
    entity2.money += amount
    yield entity1.put_async(), entity2.put_async() # parallel

transfer_money(key1, key2, amount).check_success()

这比连续使用 getput 或它们的 multi 变体更快、更有效。