Атомарные операции в Django?

Указатель NULL - это тот, который указывает на никуда. Когда вы разыскиваете указатель p, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p является нулевым указателем, местоположение, хранящееся в p, является nowhere, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception.

В общем, это потому, что что-то не было правильно инициализировано.

24
задан RichVel 15 March 2014 в 11:09
поделиться

7 ответов

Это - определенный взлом. Необработанный SQL сделает Ваш код менее портативным, но это избавится от состояния состязания на встречном инкременте. В теории это должно увеличить счетчик любое время, Вы делаете запрос. Я не протестировал это, таким образом, необходимо удостовериться, что список интерполирован в запросе правильно.

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()
1
ответ дан iconoplast 28 November 2019 в 23:03
поделиться

Если Вы действительно хотите в противоречии с, точны, Вы могли бы использовать транзакцию, но сумма требуемого параллелизма действительно ослабит Ваше приложение и базу данных при любой значительной загрузке. Вместо этого думайте о движении с большим количеством обменивающегося сообщениями подхода стиля и просто ведите учет количества дампа в таблицу для каждого посещения, где Вы хотели бы увеличить счетчик. Тогда, когда Вы хотите общее количество посещений, проводят подсчет на таблице посещений. У Вас мог также быть фоновый процесс, который выполнил любое количество раз день, который суммирует посещения и затем сохранит это в родительской таблице. Чтобы экономить на пространстве, это также удалило бы любые записи из дочерней таблицы посещений, которой это подвело итог. Вы сократите свои затраты параллелизма огромная сумма, если у Вас не будет нескольких агентов, соперничающих за те же ресурсы (счетчик).

12
ответ дан Sam Corder 28 November 2019 в 23:03
поделиться

Можно использовать патч от http://code.djangoproject.com/ticket/2705 для блокировки уровня базы данных поддержки.

С патчем этот код будет атомарным:

visitors = VisitorDayTypeCounter.objects.get(day=curday).for_update()
visitors.counter += 1
visitors.save()
6
ответ дан kmmbvnr 28 November 2019 в 23:03
поделиться

Почему бы не использовать базу данных в качестве слоя параллелизма? Добавьте первичный ключ или ограничение на уникальность данных таблица к visitType и visitDate. Если я не ошибаюсь, django точно не поддерживает это в их классе модели базы данных, или по крайней мере я не видел примера.

, Как только Вы добавили ограничение/ключ к таблице, тогда все, которое необходимо сделать:

  1. проверка, если строка там. если это, выберите его.
  2. вставляют строку. если нет никакой ошибки, Вы в порядке и можете идти дальше.
  3. , если существует ошибка (т.е. состояние состязания), повторно выберите строку. если нет никакой строки, то это - подлинная ошибка. Иначе Вы в порядке.

Это противно, чтобы сделать это этот путь, но это кажется достаточно быстрым и покрыло бы большинство ситуаций.

1
ответ дан Roopinder 28 November 2019 в 23:03
поделиться

Два предложения:

Добавляют unique_together к Вашей модели и обертывают создание в обработчик исключений для ловли дубликатов:

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

После этого у Вас могло все еще быть незначительное состояние состязания на обновлении счетчика. Если бы Вы заставляете достаточно трафика быть затронутым, о котором, я предложил бы изучить транзакции для более прекрасного гранулярного управления базой данных. Я не думаю, что ORM имеет прямую поддержку блокировки/синхронизации. Документация транзакции доступна здесь .

5
ответ дан Daniel Naab 28 November 2019 в 23:03
поделиться

Ваш должен использовать транзакции базы данных для предотвращения этого вида состояния состязания. Транзакция позволяет Вам выполнить целую операцию создания, чтения, постепенного увеличения и сохранения счетчика на "все или ничего" основа. Если что-нибудь пойдет не так, как надо, то это будет откатывать все это, и можно попробовать еще раз.

Выезд Django документы. существует изделие середины транзакции, или можно использовать декораторов вокруг представлений или методов для создания транзакций.

0
ответ дан Ber 28 November 2019 в 23:03
поделиться

Начиная с Django 1.1 вы можете использовать выражения F () ORM.

from django.db.models import F
product = Product.objects.get(name='Venezuelan Beaver Cheese')
product.number_sold = F('number_sold') + 1
product.save()

Подробнее см. Документацию:

https://docs.djangoproject.com/en/1.8/ref/models/instances/#updating-attributes-based-on-existing-fields

https: //docs.djangoproject.com/en/1.8/ref/models/expressions/#django.db.models.F[1247pting

29
ответ дан 28 November 2019 в 23:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: