我们注意到 django 应用程序中使用 get_or_create 时存在很多问题。
model, created = SomeModel.objects.get_or_create(user=user, name=name, defaults={...});
if created:
get_some_dimensions # SLOW as we call to third party
model.dimension_values.set(created_dimensions)
# Code here that depends on dimensions being there for the model
问题是上面的代码同时运行了两次。
在第 3 步,数据库转换为错误状态。
如何防止第二次实际运行,锁定数据库,直到构建完整对象?
将其包装在交易中?
with transaction.atomic():
model, created = SomeModel.objects.get_or_create(user=user, name=name, defaults={...});
if created:
get_some_dimensions # SLOW as we call to third party
model.dimension_values.set(created_dimensions)
# model.save() if .set doesn't do that
# the object doesn't exist until here where the transaction completes (exit with block)
但我不是数据库专家,所以我不确定如果在第三方速度缓慢时发生另一个
get_or_create
会发生什么。数据库是否会停止第二个操作直到事务终止?如果第三方请求可能需要几十秒,用户是否会认为这是一个错误?
另一种方法是测试是否
SomeModel.objects.filter(...).exists()
,如果不是,则在执行get_or_create
之前向慢速第三方请求信息(向该调用提供第三方信息,以便在完整状态下创建对象)。这里唯一的缺点是可能会向第三方重复请求不需要的信息。 (每次通话要花很多钱吗?)