Django数据库并发问题
Django database concurrency problems
我在 Web api 中有一个 "single" 方法可以调用两个数据库
- 使用 count() 确保特定对象不存在
- 如果对象不存在就保存它
这里的逻辑显然不是保存已经存在的对象。很简单。
当重复的对象开始出现在数据库 table 中时,问题就来了。然后我意识到我无法控制不良的客户端调用(同时重复调用)。
因此,当第二次调用此方法恰好发生在具有相同参数(相同对象)的代码块 1) 和 2) 之间时,就会出现问题:
- 调用 1 => count() == 0
- 调用 2 => count() == 0(它是 0,因为第一个调用没有完成
此时处理并保存对象)
- 调用 1 => 保存对象
- 调用 2 => 保存对象,因为 count() == 0
错误结果 => 我的 table 有两行具有相同的值
所以我需要在 "Call 1" 代码块完成之前不处理 "Call 2"。
我一直在研究这个问题。一个选项是阻止 table 我查询直到方法完成执行(但这会给等式带来新的问题)。
其他人正在谈论使用原子事务,但我看不出如果另一个调用同时运行,这有什么帮助。
另一种可能的解决方案是使用 unique_together,因此不可能创建具有相同值的两行(我开始认为这将是最佳选择)
我迷路了,想弄清楚如何解决这个问题。
鉴于这个问题很难测试我想先在这里问。也许我只是遗漏了一些明显简单的东西......
澄清一下,这是我判断对象是否已经存在的方式:
# return error if the follow is already done
current_follow_query = request.user.follows.filter(influencer=influencer)
if current_follow_query.count() > 0:
return Response(status=status.HTTP_204_NO_CONTENT)
# save the actual follow object
obj = Follow(follower=request.user, influencer=influencer)
obj.save()
有什么想法吗?
因此,当您通过 influencer
和 follower
两个字段定义标识时,它们必须是唯一的。只需使用 unique_together = [('influencer', 'follower')]
约束将其告知数据库即可。
现在为了保存,你会希望依靠数据库来执行这个测试:只需一直保存并在错误发生时进行处理。
from django.db import IntegrityError
try:
obj = Follow.objects.create(follower=request.user, influencer=influencer)
except IntegrityError:
# the object already existed!
else:
# the object was successfully created!
我在 Web api 中有一个 "single" 方法可以调用两个数据库
- 使用 count() 确保特定对象不存在
- 如果对象不存在就保存它
这里的逻辑显然不是保存已经存在的对象。很简单。 当重复的对象开始出现在数据库 table 中时,问题就来了。然后我意识到我无法控制不良的客户端调用(同时重复调用)。
因此,当第二次调用此方法恰好发生在具有相同参数(相同对象)的代码块 1) 和 2) 之间时,就会出现问题:
- 调用 1 => count() == 0
- 调用 2 => count() == 0(它是 0,因为第一个调用没有完成 此时处理并保存对象)
- 调用 1 => 保存对象
- 调用 2 => 保存对象,因为 count() == 0
错误结果 => 我的 table 有两行具有相同的值
所以我需要在 "Call 1" 代码块完成之前不处理 "Call 2"。
我一直在研究这个问题。一个选项是阻止 table 我查询直到方法完成执行(但这会给等式带来新的问题)。
其他人正在谈论使用原子事务,但我看不出如果另一个调用同时运行,这有什么帮助。
另一种可能的解决方案是使用 unique_together,因此不可能创建具有相同值的两行(我开始认为这将是最佳选择)
我迷路了,想弄清楚如何解决这个问题。 鉴于这个问题很难测试我想先在这里问。也许我只是遗漏了一些明显简单的东西......
澄清一下,这是我判断对象是否已经存在的方式:
# return error if the follow is already done
current_follow_query = request.user.follows.filter(influencer=influencer)
if current_follow_query.count() > 0:
return Response(status=status.HTTP_204_NO_CONTENT)
# save the actual follow object
obj = Follow(follower=request.user, influencer=influencer)
obj.save()
有什么想法吗?
因此,当您通过 influencer
和 follower
两个字段定义标识时,它们必须是唯一的。只需使用 unique_together = [('influencer', 'follower')]
约束将其告知数据库即可。
现在为了保存,你会希望依靠数据库来执行这个测试:只需一直保存并在错误发生时进行处理。
from django.db import IntegrityError
try:
obj = Follow.objects.create(follower=request.user, influencer=influencer)
except IntegrityError:
# the object already existed!
else:
# the object was successfully created!