您确定它是基于争用的,还是因为上面的代码是在事务中执行的?一个快速的解决方法可能是增加重试次数并为此方法打开跨组事务:
@ndb.transactional(retries=5, xg=True)
您可以在此处阅读更多相关信息: https ://developers.google.com/appengine/docs/python/ndb/transactions 。如果这不是罪魁祸首,也许考虑推迟或异步运行删除,以便它们随着时间的推移以较小的批次执行。NDB 的诀窍是定期做少量的工作,而不是不经常地做大量的工作。这是将该代码转换为异步工作单元的一种方法:
def delete_tables_for_service(user, service):
tables = Tables.query(Tables.service == service, ancestor=user.key).fetch(keys_only=True)
for table in tables:
# Delete fields
fields_keys = Fields.query(ancestor=table).fetch(keys_only=True)
ndb.delete_multi_async(fields_keys)
# Delete table rows
table_rows_keys = TableRows.query(ancestor=table).fetch(keys_only=True)
ndb.delete_multi_async(table_rows_keys)
# Finally delete table itself
ndb.delete_async(table.key)
如果您想更好地控制删除、重试、失败,您可以使用任务队列,或者直接使用延迟库 ( https://developers.google.com/appengine/articles/deferred ):
- 在您的 app.yaml 中打开延迟
将对 ndb.delete_multi 的调用更改为延迟:
def delete_tables_for_service(user, service):
tables = Tables.query(Tables.service == service, ancestor=user.key).fetch(keys_only=True)
for table in tables:
keys = []
keys += Fields.query(ancestor=table).fetch(keys_only=True)
keys += TableRows.query(ancestor=table).fetch(keys_only=True)
keys.append(table)
deferred.defer(_deferred_delete_tables_for_keys, keys)
def _deferred_delete_tables_for_keys(keys):
ndb.delete_multi(keys)