Atomic increment of a counter in django(Django中计数器的原子增量)
问题描述
我正在尝试在 Django 中以原子方式递增一个简单的计数器.我的代码如下所示:
I'm trying to atomically increment a simple counter in Django. My code looks like this:
from models import Counter
from django.db import transaction
@transaction.commit_on_success
def increment_counter(name):
counter = Counter.objects.get_or_create(name = name)[0]
counter.count += 1
counter.save()
如果我正确理解 Django,这应该将函数包装在事务中并使增量原子化.但它不起作用,并且计数器更新中存在竞争条件.如何使这段代码成为线程安全的?
If I understand Django correctly, this should wrap the function in a transaction and make the increment atomic. But it doesn't work and there is a race condition in the counter update. How can this code be made thread-safe?
推荐答案
使用 一个 F 表达式:
from django.db.models import F
在 update()
中:
Counter.objects.get_or_create(name=name)
Counter.objects.filter(name=name).update(count=F("count") + 1)
或在对象实例上:
counter, _ = Counter.objects.get_or_create(name=name)
counter.count = F("count") + 1
counter.save(update_fields=["count"])
记得指定update_fields
,否则你可能会在模型的其他字段上遇到竞争条件.
Remember to specify update_fields
, or you might encounter race conditions on other fields of the model.
关于比赛的说明使用F表达式避免的条件已添加到官方文档中.
A note on the race condition avoided by using F expressions has been added to the official documentation.
这篇关于Django中计数器的原子增量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!