我有2个模型/表Cluster和Node,可能还有更多,每个都有" volume_limit"和" volume_count"其中的字段/列。
我想在自己的表中原子地检查计数器的限制并增加计数器。 要仅对Cluster进行原子检查和增量,我将执行以下操作
updated = Cluster.objects.filter(id=cluster_id, volume_count__lt==F('volume_limit')).update(volume_count = F('volume_count')+1)
if not updated:
raise Validation('limit reached ......')
如果我想增加节点和群集,我会添加以下内容,如果我不能递增节点计数器,这将撤消群集增量。如下所示
updated = Node.objects.filter(id=node_id, volume_count__lt==F('volume_limit')).update(volume_count = F('volume_count')+1)
if not updated:
Cluster.objects.filter(id=cluser_id).update(volume_count = F('volume_count')-1)
raise Validation('limit reached ......')
我想知道是否有办法原子地做这两件事?
基本上我想在查询/更新操作中执行以下操作
我该怎么做?
答案 0 :(得分:1)
使用transactions可以解决您的问题。你没有指定你的数据库,但是在具有默认事务隔离级别的PostgreSQL上,我相信这会有效:
with transaction.atomic():
n_updated = Node.objects.filter(
id=node_id,
volume_count__lt==F('volume_limit')
).update(volume_count=F('volume_count') + 1)
c_updated = Cluster.objects.filter(
id=cluster_id,
volume_count__lt==F('volume_limit')
).update(volume_count=F('volume_count') + 1)
if not (n_updated and c_updated):
# trigger rollback
raise ValidationError("Limit reached")
关键是您要定位特定的行,并且如果可能的话更新它们,如果他们尝试更新相同的行,这将导致其他事务阻止。由于它是一个交易,要么两个更新都会成功,否则都不会。