Django get_or_create因多处理而失败.Pool

时间:2016-07-15 12:16:14

标签: python django postgresql multiprocessing

这是我的项目设置,使用标准的Django startproject命令和一个应用程序:

Python 3.5.1
Django 1.9.7
PostgreSQL 9.5.3
Ubuntu 16.04

应用程序的models.py定义了2个模型:

from django.db import models

class A(models.Model):
    n = models.PositiveIntegerField(primary_key=True)

class B(models.Model):
    a = models.ForeignKey(A, blank=True, null=True)
    m = models.CharField(max_length=20, db_index=True)

    class Meta:
        unique_together = ('a', 'm')

    def __str__(self):
        return '%s' % self.m

这是我的名为execute.py的管理命令,用于创建B的实例:

from multiprocessing import Pool
from django import db
from django.core.management.base import BaseCommand
from .models import B

M = 'abcdef'

def create():
    obj, created = B.objects.get_or_create(m=M, defaults={'a': None})
    if created:
        print('obj=%s' % obj)

class Command(BaseCommand):
    def handle(self, *args, **kwargs):
        B.objects.filter(m=M).delete()
        db.connections.close_all()
        n = 4
        pool = Pool(processes=n)
        results = []
        for _ in range(n):
            result = pool.apply_async(create)
            results.append(result)
        pool.close()
        for result in results:
            result.get()
        pool.join()

运行 python manage.py execute 会导致创建4个obj而不是1。但情况并非总是这样。有时,只创建了3个甚至只有1个对象:

obj=abcdef
obj=abcdef
obj=abcdef
obj=abcdef

我是否遗漏了一些在这里强制执行的独特性?

1 个答案:

答案 0 :(得分:0)

documentation for get_or_create()

中解释了此行为
  

此方法是原子的,假设正确使用,正确的数据库配置和底层数据库的正确行为。 但是,如果未在数据库级别强制执行唯一性 [...],则此方法容易出现竞争条件,这可能会导致多行具有相同的参数同时插入。

function clicker(){ alert ("Step 1.9: Clearly it is entering func"); $("#button").click(function(){ alert("Step 2 ALERT"); //SKIPS THIS PART }) } $(document).ready(function(){ alert("hello, step 1"); if (1==1) { clicker(); alert("Step 3:Done with 'if' "); } alert("step 4 DONE with whole code"); }) 模型的m字段没有B约束,这导致竞争条件。将字段定义更改为:

unique=True

你应该没事。