我在方法中有以下代码,它被装饰为事务性的:
@ndb.transactional(retries=2, xg=True)
def add_insights(self, insights, countdown = True, forced_finish = False):
...
thing = tkey.get() ###############
logging.debug(thing.open_enrichments)
thing.insights += insight_keys
if countdown and not forced_finish:
thing.open_enrichments -= 1
if thing.open_enrichments < 0:
thing.open_enrichments = 0
elif forced_finish:
thing.open_enrichments = 0
logging.debug(thing.open_enrichments)
thing.put() #########################
此方法在许多并发任务中运行,这些任务可能访问NDB中的同一“事物”实体。当我检查日志文件(为了清楚起见简化调试语句)时,似乎即使这个代码在一个任务中失败,另一个任务仍然可能从失败的任务中的递减计数器“open_enrichments”开始。
我通过按时间戳对调试语句进行排序来验证这一点。
当然,由于这个问题,计数器的速度太快了。 open_enrichments最初设置为8但是得到(对于使用key.get()读取计数器的其他任务有效)减少了12或13次,我从NDB中了解的事务中不了解。
编辑:
澄清顺序:
所以这两个任务只成功运行了两次,但计数器减少了3 !!
答案 0 :(得分:0)
Appengine事务实际上可以提交但仍然失败,并且会被重试(默认情况下为3次)。请参阅this page上的第一个注释。
因此,您的交易是幂等的非常重要。您是否可以将open_enrichments设置为给定数字而不是在事务中递减?