为了账号安全,请及时绑定邮箱和手机立即绑定

transaction.atomic 是否有可能无法按预期工作?

transaction.atomic 是否有可能无法按预期工作?

侃侃尔雅 2022-10-25 09:44:01
这是一个用于条目的 DRF API 视图。当有人喜欢一个条目时,我会将一条喜欢的记录插入到表中entry_like,并加 1 到likes_num另一个表中的字段entry。但是,一个条目对应的某些entry_like记录数少于likes_numtable 中的字段出现了问题entry。我不知道为什么即使该post方法使用了装饰器,它也不能按预期工作transaction.atomic。是否存在装饰transaction.atomic器未按预期运行的情况?
查看完整描述

2 回答

?
交互式爱情

TA贡献1712条经验 获得超3个赞

是的,我认为这种情况transaction.atomic()并不像您期望的那样工作。

要了解它的作用,您必须了解 SQL 的事务隔离级别以及它们所保证的确切行为。你没有提到你正在使用什么数据库,但是 PostgreSQL 有很好的关于这个主题的文档。

您的期望似乎是它会像隔离级别一样工作SERIALIZABLE。事实上,Django 中默认的隔离级别是READ COMMITTED. 在那个隔离级别下,如果你有两个这样的事务同时运行,它们都会被likes_num相同的数字覆盖。

一种解决方案是使用 F 对象而不是设置likes_num为特定值。在这种情况下,新值将基于写入时字段中的任何值,而不是读取行时字段中的值。

entry.likes_num = F('likes_num') + 1

另一种解决方案是使用select_for_update(),它将锁定entry行。如果可以的话,最好避免使用锁,所以我会选择 F-object 版本。


查看完整回答
反对 回复 2022-10-25
?
慕标琳琳

TA贡献1830条经验 获得超9个赞

我认为您需要使用 F 对象


from django.db.models import F


...

entry.likes_num = F('likes_num') + 1

entry.save()

因为您在代码执行中没有任何错误,并且两个事务是有效的。


查看完整回答
反对 回复 2022-10-25
  • 2 回答
  • 0 关注
  • 75 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信