Избегайте уникальных нарушений ограничений при одновременной вставке данных

Я реализую импортер, использующий пул рабочих (на основе Celery и RabbitMQ). Импортируемые данные включают пользовательские данные, идентифицируемые уникальным идентификатором пользователя, и сохраняются в базе данных PostgreSQL.

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

Если данные для определенного идентификатора пользователя уже существуют, проблем нет: строка базы данных блокируется с помощью SELECT ... FOR UPDATE. Однако, если нет данных, связанных с идентификатором, оба импорта могут столкнуться с неприятной ситуацией, когда оба пытаются INSERT — использовать один и тот же идентификатор пользователя.

Поскольку поле идентификатора пользователя имеет ограничение UNIQUE, транзакции не выполняются.

Как я могу предотвратить это? Есть ли другие варианты, кроме блокировки всей таблицы?


person stschindler    schedule 02.06.2016    source источник
comment
@xQbert Не совсем так, моя проблема в том, что две одновременные транзакции пытаются INSERT выполнить обе одновременно, где одна, конечно, всегда терпит неудачу. Это происходит потому, что я не знаю надежного способа блокировки этой операции, например: Блокировать любые будущие INSERT операции, которые пытаются вставить с идентификатором пользователя = 1234.   -  person stschindler    schedule 02.06.2016
comment
Но upsert, как предложил @xQbert, действительно здесь работает.   -  person e4c5    schedule 02.06.2016
comment
Да, я неправильно понял другой вопрос, извините. Жаль, что Джанго этого не поддерживает. Спасибо!   -  person stschindler    schedule 02.06.2016