我在 Web api 中有一个“单一”方法,可以进行两次数据库调用
- 使用 count() 确保特定对象不存在
- 如果对象不存在,则保存它
这里的逻辑显然不是保存已经存在的对象。很简单。当重复的对象开始出现在 db 表中时,问题就来了。然后我意识到我无法控制糟糕的客户呼叫(同时重复呼叫)。
因此,当对该方法的第二次调用恰好发生在具有相同参数(相同对象)的代码块 1) 和 2) 之间时,就会出现问题:
- 调用 1 => count() == 0
- 调用 2 => count() == 0(它是 0,因为此时第一次调用没有完成处理和保存对象)
- 调用 1 => 保存对象
- 调用 2 => 保存对象,因为 count() == 0
错误的结果 => 我的表有两行具有相同的值
因此,在“Call 1”代码块完成之前,我不需要处理“Call 2”。
我一直在研究这个很多。一个选项会阻止我正在查询的表,直到方法完成执行(但这会给等式带来新的问题)。
其他人正在谈论使用原子事务,但我不明白如果另一个调用同时运行会有什么帮助。
另一种可能的解决方案是使用 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()
有任何想法吗?