Django создает повторяющиеся отношения следования - возможны проблемы параллелизма при создании новых данных в таблице - PullRequest
1 голос
/ 03 февраля 2012

Позвольте мне объяснить мою конкретную ситуацию:

Бизнес может выбрать район, в котором он находится, эта опция сохраняется в БД, при сохранении этих объектов подается сигнал. Метод прослушивает этот сигнал и должен только один раз обновить всех других пользователей, которые также следуют этому соседству. В этом методе выполняется проверка, пытающаяся проверить, следует ли любому другому пользователю уже следовать этому бизнесу, для каждого пользователя, который не следует этому бизнесу, но следует по этому соседству, в БД будет создано следующее отношение. Все должно быть хорошо, если пользователь уже следит за этим бизнесом, то никакого отношения не установлено ...

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

Я пытался убедиться, что сигнал не отправляется несколько раз, но я не уверен, почему эти несколько транзакций происходят одновременно.

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

Является ли блокировка таблицы единственным способом, гарантирующим, что произойдет только одна вставка?

# when a business updates their neighborhood, this sets the follow relationship

def follow_biz(sender, instance, created, **kwargs):

    if instance.neighborhood:
        neighborhood_followers = FollowNeighborhood.objects.filter(neighborhood=instance.neighborhood)
        # print 'INSTANCE Neighborhood %s ' % instance.neighborhood
        for follower in neighborhood_followers:

            if not Follow.objects.filter(user=follower.user, business=instance).count():
                follow = Follow(business=instance, user=follower.user)
                follow.save()

# a unique static string to prevent signal from being called twice
follow_biz_signal_uid = hashlib.sha224("follow_biz").hexdigest()

# signal
post_save.connect(follow_biz, sender=Business, dispatch_uid=follow_biz_signal_uid)

1 Ответ

0 голосов
/ 03 февраля 2012

Обеспечивая уникальность [1] строк на уровне базы данных, используя ограничение на соответствующие столбцы, Django, AFAICT, будет делать правильные вещи и вставлять или обновлять при необходимости.

В этом случае ограничение должно быть на пользователя и бизнес-идентификатор.

[1] Конечно, всегда полезно обеспечить уникальность, где это применимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...