1

我有一组我写的芹菜任务。这些任务中的每一个都以作者 ID 作为参数——只是一个例子——作为参数,对于作者的每本书,它获取最新价格并将其存储在数据库中。

我想通过将 Django 的 @transaction.commit_on_success装饰器添加到我的任务中来将事务添加到我的任务中。如果任何任务崩溃,我希望整个任务都失败,并且没有任何内容可以保存到数据库中。

我有十几个芹菜工人检查作者的书籍价格,我想知道这个简单的事务逻辑是否会导致我的 Postgres 数据库中的锁定和竞争条件。

我已经挖掘并发现了这个名为django-celery-transactions 的项目,但我仍然不了解这背后的真正问题以及该项目试图解决的问题。

4

2 回答 2

1

这取决于几件事,包括:数据库的事务隔离级别、检查价格更新的频率以及期望价格变化的频率。例如,如果您每秒对标准PostgreSQL进行大量更新,您可能会在事务中多次执行相同的 select 语句得到不同的结果。

数据库经过优化以处理并发性,所以我认为这对您来说不是问题;特别是如果您在获取价格后才打开交易(即使用上下文管理器而不是装饰任务)。如果 - 由于某种原因 - 未来事情变得缓慢,那么优化(不那么频繁地获取价格,调整数据库配置等)。

至于你的其他问题:django-celery-transactions 旨在防止 Django 和 Celery 之间的竞争条件。一个示例是,如果您要将新创建的对象的主键传递给任务:该任务可能会在视图的事务提交之前尝试检索该对象。繁荣!

于 2012-10-19T11:51:16.380 回答
1

原因是在您的 Django 视图中,如果您应用装饰器,则在视图退出之前不会提交数据库事务。在视图返回并触发提交之前,您可以调用期望 DB 事务已经提交的任务,即那些条目存在于 DB 上下文中。

为了防止这种竞争条件(任务在您的视图之前开始并因此事务完成)您可以手动管理它或使用您提到的自动为您处理它的模块。

例如,在您的情况下,它可能会失败的示例是,如果您要添加新作者,并且您有一项任务可以获取所有/任何书籍的价格。如果任务在新作者事务的提交完成之前执行,您的任务将尝试使用尚不存在的 id 获取作者。

于 2012-10-19T07:28:37.700 回答