在Django中保存数据时Celery死锁,为什么?

时间:2014-12-08 13:36:40

标签: python django celery

使用 Celery 任务从CSV保存新客户时,我有死锁。这就是我到目前为止所做的工作。

  for line in csv.reader(instance.data_file.read().splitlines()):
        for index, item in enumerate(line):
            number = int(item)
            # TODO: Turn into task
            Customer.objects.create_customer(
                mobile=number,
                campaign=instance.campaign,
                reward_group=instance.reward_group,
                company=instance.company,
            )

没有错误。

但是,当将相同的代码添加到Celery任务时,我会收到以下错误...

  

试图锁定时发现死锁;尝试重新启动事务'

所以,这让我相信我的芹菜设置做错了。谁能发现什么?

这是新的Celery任务,它给出了死锁错误。我正在使用shared_task,因为这些任务在某些时候会运行在没有Django的不同机器上,但这现在无关紧要。

CSV导入的第一行ok,然后我遇到死锁错误......

for line in csv.reader(instance.data_file.read().splitlines()):
    for index, item in enumerate(line):
        number = int(item)
        celery_app.send_task('test.tasks.create_customer_from_import', args=[number, instance.id], kwargs={})

tasks.py

# Python imports
from __future__ import absolute_import

# Core Django imports
from celery import shared_task

from mgm.core.celery import app as celery_app

@shared_task
def create_customer_from_import(number, customer_upload_id):
    customer_upload = CustomerUpload.objects.get(pk=customer_upload_id)
    new_customer = Customer.objects.create_customer(
        mobile=number,
        campaign=customer_upload.campaign,
        reward_group=customer_upload.reward_group,
        company=customer_upload.company,
    )
    return new_customer

celery.py

from __future__ import absolute_import

import os

from celery import Celery

from django.conf import settings

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'test.settings')

app = Celery('test-tasks')

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

这是CustomerManager:

class CustomerManager(models.Manager):
    def create_customer(self, mobile, campaign, reward_group, company, password=None):.
        user = AppUser.objects.create_user(mobile=mobile)
        # Creates a new customer for a company and campaign
        customer = self.model(
            user=user,
            campaign=campaign,
            reward_group=reward_group,
            company=company
        )

        customer.save(using=self._db)

1 个答案:

答案 0 :(得分:4)

您的代码看起来并不错,但由于多个芹菜工人的并发性,您可能会陷入僵局。来自http://celery.readthedocs.org/en/latest/faq.html#mysql-is-throwing-deadlock-errors-what-can-i-do

  

如果不这样做,MySQL的默认隔离级别设置为REPEATABLE-READ   真的需要,把它设置为READ-COMMITTED。你可以通过添加来做到这一点   以下是你的my.cnf:

[mysqld]
transaction-isolation = READ-COMMITTED