Как безопасно переслать последовательность первичных ключей в Django? - PullRequest
1 голос
/ 16 февраля 2012

Используя Django с бэкэндом PostgreSQL (8.x), у меня есть модель, где мне нужно пропустить блок идентификаторов, например. после выдачи 49999 я хочу, чтобы следующий идентификатор был 70000, а не 50000 (потому что этот блок зарезервирован для другого источника, где экземпляры явно добавляются с идентификатором - я знаю, что это не очень хороший дизайн, но это то, с чем мне приходится работать).

Какое самое правильное / безопасное место для этого?

Я знаю, что могу установить последовательность с помощью

SELECT SETVAL(
    (SELECT pg_get_serial_sequence('myapp_mymodel', 'id')),
    70000,
    false
);

но когда Django фактически вытаскивает число из последовательности? Должен ли я переопределить MyModel.save (), вызвать его супер, а затем схватить меня курсор и проверить с помощью

SELECT currval(
    (SELECT pg_get_serial_sequence('myapp_mymodel', 'id'))
);

Я полагаю, что django может продвинуть последовательность даже в случае сбоя при сохранении модели, поэтому я хочу убедиться, что всякий раз, когда она достигает того числа, которое она опережает, есть ли место лучше, чем save ()?

P.S .: Даже если это был путь - могу ли я на самом деле выяснить курс для сессии save (), как это? если я возьму у меня соединение и курсор и выполню этот второй оператор SQL, я не буду в другом сеансе и, следовательно, не получу курс?

Спасибо за любые указатели.

РЕДАКТИРОВАТЬ : У меня такое чувство, что это должно быть сделано на уровне базы данных (проблемы параллелизма), и я отправил соответствующий вопрос PostgreSQL - Как безопасно переслать последовательность первичного ключа в PostgreSQL? 1022 *

Ответы [ 2 ]

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

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

Ноэтот же механизм легко реализуется на уровне postgres - я считаю, что это решение:

  • Не используйте SERIAL для первичного ключа, используйте DEFAULT my_next_id ()
  • Followта же логика, что и для «одноуровневой последовательности без промежутков» - http://www.varlena.com/GeneralBits/130.php - my_next_id () выполняет обновление с последующим выбором
  • Вместо того, чтобы просто увеличивать на 1, проверить, была ли граница пересеченатак что увеличивайте еще больше
0 голосов
/ 20 февраля 2012

Поскольку я еще не нашел «автоматизированный» способ сделать это, я думаю о следующем обходном пути - это было бы целесообразно для моей конкретной ситуации:

  1. Установите последовательность с помощью MAXVALUE 49999 NO CYCLE
  2. Когда достигается 49999, следующее сохранение () приведет к ошибке postgres
  3. Поймайте это исключение и вызовите ошибку формы "у вас закончились номера, пожалуйста, вернитесь к следующему блоку и повторите попытку"
  4. Предоставить представление, где пользователь может активировать следующий блок, то есть выполнить «ALTER SEQUENCE my_seq RESTART WITH 70000 MAXVALUE 89999»

Меня не устраивает автоматический перезапуск при обнаружении исключения:

try:
    instance.save()
except RunOutOfIdsException:
    restart_id_sequence()
    instance.save()

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

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