我有一个只能使用get_or_create(session=session)
访问的Django模型,其中session是另一个Django模型的外键.
因为我只能通过get_or_create()
访问,所以我可以想象,我只有一个实例具有会话密钥.但是,我发现多个实例具有同一会话的密钥.发生了什么事?这是一个竞赛条件,还是get_or_create()
是原子运行的?
我有一个只能使用get_or_create(session=session)
访问的Django模型,其中session是另一个Django模型的外键.
因为我只能通过get_or_create()
访问,所以我可以想象,我只有一个实例具有会话密钥.但是,我发现多个实例具有同一会话的密钥.发生了什么事?这是一个竞赛条件,还是get_or_create()
是原子运行的?
实际上它不是线程安全的,您可以查看QuerySet对象的get_or_create方法的代码,它的基本功能如下:
try:
return self.get(**lookup), False
except self.model.DoesNotExist:
params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])
params.update(defaults)
obj = self.model(**params)
sid = transaction.savepoint(using=self.db)
obj.save(force_insert=True, using=self.db)
transaction.savepoint_commit(sid, using=self.db)
return obj, True
因此,在连续保存实例之前,两个线程可能会发现数据库中不存在该实例,并开始创建一个新实例.