本文介绍了Django中的原子操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图实现(我认为)一个很简单的数据模型为计数器:

I'm trying to implement (what I think is) a pretty simple data model for a counter:

class VisitorDayTypeCounter(models.Model):
    visitType = models.CharField(max_length=60)
    visitDate = models.DateField('Visit Date')
    counter = models.IntegerField()

当有人通过时,它将查找与visitType和visitDate匹配的行;如果此行不存在,则将使用counter = 0创建。

When someone comes through, it will look for a row that matches the visitType and visitDate; if this row doesn't exist, it will be created with counter=0.

然后我们递增计数器并保存。

Then we increment the counter and save.

我担心的是,这个过程完全是一场比赛。两个请求可以同时检查实体是否存在,并且它们都可以创建它。在读取计数器和保存结果之间,另一个请求可以通过并增加它(导致一个丢失的计数)。

My concern is that this process is totally a race. Two requests could simultaneously check to see if the entity is there, and both of them could create it. Between reading the counter and saving the result, another request could come through and increment it (resulting in a lost count).

到目前为止,我没有真正找到一个好方法是在Django文档或教程中(实际上,教程在Vote部分中有一个竞争条件)。

So far I haven't really found a good way around this, either in the Django documentation or in the tutorial (in fact, it looks like the tutorial has a race condition in the Vote part of it).

如何我这样做是否安全?

How do I do this safely?

推荐答案

这是一个黑客。原始SQL将使你的代码更少的可移植性,但它会摆脱计数器增量的竞争条件。理论上,这应该增加计数器在任何时候你做一个查询。我没有测试这个,所以你应该确保列表在查询中正确插入。

This is a bit of a hack. The raw SQL will make your code less portable, but it'll get rid of the race condition on the counter increment. In theory, this should increment the counter any time you do a query. I haven't tested this, so you should make sure the list gets interpolated in the query properly.

class VisitorDayTypeCounterManager(models.Manager):
    def get_query_set(self):
        qs = super(VisitorDayTypeCounterManager, self).get_query_set()

        from django.db import connection
        cursor = connection.cursor()

        pk_list = qs.values_list('id', flat=True)
        cursor.execute('UPDATE table_name SET counter = counter + 1 WHERE id IN %s', [pk_list])

        return qs

class VisitorDayTypeCounter(models.Model):
    ...

    objects = VisitorDayTypeCounterManager()

这篇关于Django中的原子操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-12 15:36