Python 谷歌应用引擎NDB中的交易似乎有副作用

Python 谷歌应用引擎NDB中的交易似乎有副作用,python,google-app-engine,transactions,google-cloud-datastore,Python,Google App Engine,Transactions,Google Cloud Datastore,我在一个方法中有以下一段代码,它被修饰为事务性的: @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.ins

我在一个方法中有以下一段代码,它被修饰为事务性的:

@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中的同一事物实体。当我在这里检查日志文件debug语句时,似乎即使这段代码在一个任务中失败,另一个任务仍然可能从失败任务中的递减计数器open_enrichments开始

我通过按时间戳排序调试语句来验证这一点

当然,由于这个问题,计数器到达0的速度过快。open_enrichments最初设置为8,但在其他任务中使用键读取计数器时有效。get递减12或13次,从我在NDB中了解的事务中我不了解这一点

编辑:

为了澄清顺序:

任务A以open_enrichments=5的形式输入这段代码 任务A将这段代码保留为open_enrichments=4并失败,因为在此期间 任务B输入这段代码时,open_enrichments=4而不是5!!!!
似乎>>thing=tkey.getAppengine事务实际上可以提交,但仍然失败,默认情况下重试3次。请参见上的第一个注释


所以事务是幂等的非常重要。您能否将open_enrichments设置为给定的数字,而不是在事务中递减?

任务是否由于事务之外的原因而失败并重试?失败的不是任务,而是方法,因为事务方法的一个实例与另一个任务中的另一个实例“碰撞”。因此,该方法被重试-最多为@decorator指定的2次。我认为您需要使用父/祖先来实现强一致性:好吧,如果我使用这种方法。。。此组中的所有实体行都属于每秒小于1次写入操作的规则,这是一个相当严格的限制,如果您有数百个实体正在处理并发任务。您如何知道任务a失败?日志条目不会告诉你,时间也不会一致。ie:如果任务A进入并离开,那么任务B进入并离开,日志条目可能会转到任务A进入、任务B进入、任务A离开、任务B离开。