用 get_or_create 多线程创建数据时会产生重复数据;
方法的源码如下:
def get_or_create(self, defaults=None, **kwargs): """ Looks up an object with the given kwargs, creating one if necessary. Returns a tuple of (object, created), where created is a boolean specifying whether an object was created. """ lookup, params = self._extract_model_params(defaults, **kwargs) # The get() needs to be targeted at the write database in order # to avoid potential transaction consistency problems. self._for_write = True try: return self.get(**lookup), False except self.model.DoesNotExist: return self._create_object_from_params(lookup, params)
问题解决:
在创建表的时候指定联合索引;
配合事务一起使用;
在model层加限制unique或 unique_together
例子如下:
class PangleData(models.Model): time_zone = models.CharField(max_length=3, verbose_name='Timezone') currency = models.CharField(max_length=32, verbose_name='Currency') region = models.CharField(max_length=6, verbose_name='Region') app_id = models.IntegerField(verbose_name='App id on Pangle platform') app_name = models.CharField(max_length=32, verbose_name='App Name on Pangle platform') ad_slot_id = models.BigIntegerField(verbose_name='Placement id on Pangle platform') ad_slot_type = models.IntegerField(verbose_name='Also known as Ad type') package_name = models.CharField(max_length=32, verbose_name='Package name') request = models.IntegerField(verbose_name='request') P_return = models.IntegerField(verbose_name='return') fill_rate = models.FloatField(null=True, verbose_name='fill_rate') show = models.IntegerField(verbose_name='Impressions') click = models.IntegerField(verbose_name='click') click_rate = models.FloatField(verbose_name='Click Through Rate') revenue = models.FloatField(verbose_name='Estimated Revenue') ecpm = models.FloatField(verbose_name='Estimated Ecpm') media_name = models.CharField(max_length=12, verbose_name='Account name') code_name = models.CharField(max_length=64, verbose_name='Slot name on Pangle platform') os = models.CharField(max_length=12, verbose_name='Operating system') use_mediation = models.IntegerField(verbose_name='Is use pangle mediation. 0 (Not) 、1 (Yes)') bidding_type = models.IntegerField(verbose_name='RIT bidding type. 0 (standard) 、1 (in-app bidding) 、' '2 (client bidding)') date = models.DateField(null=True, verbose_name='Date') media_m_ssr = models.IntegerField(verbose_name='media_m_ssr') class Meta: unique_together = ['region', 'app_id', 'ad_slot_id']