这是在appengine transaction docs ...
注意:如果您的应用程序在提交事务时收到异常,则并不总是意味着事务失败。在已提交事务并最终成功应用事务的情况下,您可以收到Timeout,TransactionFailedError或InternalError异常......
考虑以下情况
A
。db.get(entity_a_key_goes_here)
。None
,我会通过将密钥设置为entity_a_key_goes_here
和db.put()
来创建该实体(步骤3和此步骤在同一事务中运行)。我的问题:
上面第3步的事务性 db.get()
操作是否有可能返回过时值(或者不是第1步中设置的更新值)?事务性db.get()
操作是否保证即使在它之前发生“怪异”事务异常也会返回最新鲜的结果?
答案 0 :(得分:1)
我认为在这种情况下第3步的结果将是一个陈旧的价值。在这种情况下,“最新鲜”的结果可能不是步骤1中的实体。
我的建议是在检索值时使用memcache(当memcache未命中时回退到db.get()
调用),并在更新实体时更新memcache。使用实体密钥作为内存缓存密钥。实际上,这就是ndb自动运行的方式。
答案 1 :(得分:1)
获取并不是真正的“交易”;如果事务只包含读取,则提交事务实际上不会执行任何操作。在事务中执行读取只保证一件事:如果在应用事务中的任何写入时,返回的读取值不再是最新值,则事务将中止且不会写作将会发生。
因此,允许发生以下事件序列:
但是,这一系列事件是不同的:
因此,在您的第4步添加到问题中,您处于第二个事件序列中。即使实体确实存在,步骤3中的get也可能返回None,但在后一种写入成功的情况下 可能:事务已过期,因此无法提交。事务将被重试,第二次,get将返回步骤1中写入的对象,这就是你想要的。
所以非常简短的答案是:是的,它可以返回一个陈旧的值,但是如果结果是陈旧的,那么保证在同一个事务中对该实体的后续写入将失败,所以这实际上不应该导致问题。
答案 2 :(得分:0)
根据我在“ndb”上阅读的文档,我了解如果您在“交易”(get()
)中运行put()
和@ndb.transactional
,那么您就不会得到过时的数据。 'ndb'将提供更新的数据或两者都失败。
交易失败或成功。与其他dbms一样,ndb也维护'journal'。
希望这有帮助。