【发布时间】:2013-07-14 08:04:54
【问题描述】:
如果我们在 appengine 上启动一个删除复杂对象的事务,并且该对象附加了一些需要删除的 blob 引用,那么我们就有问题了。如果我们只是删除 blob,则事务可能会失败,但 blob 会消失,因为 blobstore 是独立工作的(这与事务的想法背道而驰)。
现在我们有了这个很酷的新 NDB,它有一个上下文缓存,没有记录的 API(?)可以解决问题。
工具箱:
- ndb.get_context()(未在 ndb 的函数参考中记录)
-
ndb_context.call_on_commit(delete_blobs_call_on_commit)
def delete_blobs_call_on_commit(): ndb_context = ndb.get_context() blobstore.delete(ndb_context.list_of_blobkeys_to_delete) # OR: taskqueue.add(url+ndb_context.list_of_blobkeys_to_delete)
任务:将事务期间要删除的 blobkey 附加到上下文对象,并在事务后将其删除。
更新:call_on_commit() 不允许数据库操作(可能包括 blobstore.delete,但尚未尝试过)并且会抛出 BadRequestError: Cannot start a new operation in a finished transaction,所以唯一的解决方案可能真的是任务队列。
更新:可以从使用 call_on_commit() 注册的函数调用带有 @ndb.non_transactional 装饰器的函数。因此,可以尝试在提交成功时删除 blob,并希望您没有会导致孤儿的异常。
问题:如何安全地使用上下文缓存?您是如何解决 blob 删除问题的?
【问题讨论】:
-
这将如何解决问题?删除 blobkey 可能仍会失败,现在您有孤立 blobkey。考虑使用前滚事务模型,跟踪两个删除,在任务中运行它。然后,该任务可以确认它已删除所有内容,然后自行清理。如果它在任何时候失败,清扫器可以向前滚动并重试,直到所有实体都消失。只是一个建议。
-
我考虑将所有 blob 删除推入任务队列并在事务失败时删除任务,但这很不方便。 delete_blobs_call_on_commit() 仍然可以使用任务队列而不是直接删除 blob,但我认为有一些孤儿是可以接受的。如果 blobstore 的成功率达到 99.9%,那就没问题了。这个问题主要涉及收集前滚数据。
-
这篇文章你看过了吗,或许会给你一些想法blog.notdot.net/2009/9/Distributed-Transactions-on-App-Engine
-
已加入书签,谢谢。
-
如果您的安全删除所有 blob 的函数需要事务,则可以在使用
@ndb.transactional(xg=True, propagation=ndb.TransactionOptions.MANDATORY)装饰它时从call_on_commit调用它。至少,到目前为止,这种方法在我的实验中是有效的。
标签: google-app-engine blobstore app-engine-ndb