Короче говоря: в веб-приложении Django для Apache2 (linux) и MySql (ISAM) нам нужно безопасно повторно использовать некоторые записи, помеченные как deleted
, вместо создания новых.Даже если больше пользователей могут запросить такие действия одновременно, каждый из них должен получить различную запись для повторного использования.
Фон:
- У нас есть веб-приложение, гдемногие пользователи могут делать что-то одновременно.
- есть таблицы, которые растут до бесконечности, но активны лишь немногие записи (иногда, например, из 100 000 длинных записей активна 1.000, и нет никаких шансов для повторной активации любого «удаленного»).)
- иногда передаются (в другие места) просто изменения, поэтому мы помечаем «удаленные» записи как таковые и переносим их для удаления записей на другой стороне
- иногда требуется для переноса таблиц(частично) в целом, и это занимает слишком много времени
- целостность данных во время передачи управляется другой частью проекта и не должна вызывать реальных проблем
Требуется:
- повторно использовать некоторые старые и давно "удаленные" записи для новых данных
- не проблема, иметь поле
reuse_me
в таблицах (по умолчанию)t False, установить True после долгого времени, удаленного некоторым скриптом).Можно смело предположить, что такие записи нигде не ссылаются и не ссылаются ни на что другое (скрипт может удалить все ссылки из записи и пометить только не ссылочные записи, поэтому древовидные структуры будут освобождены за большее количество шагов - нетциклические структуры для освобождения в любом случае, и если они станут, может быть другой способ отключить их как единое целое) - есть проблема, как выбрать их для использования, когда более чем один пользователь может попробовать этов то же время (как побочный эффект присутствия в сети)
Простое решение (не работает во многих случаях):
- некоторые записи легкописать полностью за один раз с помощью чистого SQL (что-то вроде
UPDATE car_owners_cross SET deleted=0, resuse_me=0, owner_id=123, car_type_id=456 WHERE deleted=1 AND resuse_me=1 LIMIT 1;
), и он (должен) выбрал бы «произвольную свободную запись» и переписал бы ее, чтобы она больше не была свободной и не было никакого конфликта.(также это будет сделано только в том случае, если число бесплатных записей больше, чем, скажем, 100, в противном случае это будет просто ВСТАВЛЕНО - поэтому не беспокойтесь о том, что не найдете бесплатную запись в параллельном доступе)
Общее решение:
- некоторые записи являются более сложными и требуют многократного обновления до тех пор, пока задача не будет выполнена (например, прикрепить файл, создать связанные записи, переписать его в зависимости от последующего веб-ввода ....), поэтому необходимознаю, какая запись была выбрана для задачи для повторного использования - и я не знаю, как это сделать
- решением должна быть функция Django, возвращающая
id
повторно использованного / созданного объекта (или объекта с действительным идентификатором) - например, coc=reuse_or_create(models.Car_Owners_Cross, owner_id=123, car_type_id=456)
или coc=models.Car_Owners_Cross.reuse_or_create(owner_id=123, car_type_id=456)
- хотя для этого, вероятно, потребуется некоторое волшебство SQL / курсоры / и т.д. внутри - Я думаю, решение будет простым, если бы был способ получить идентификатор измененной записи - таким образом, он принял бы форму
UPDATE car_owners_cross SET deleted=0, resuse_me=0 WHERE deleted=1 AND resuse_me=1 LIMIT 1;
получить идентификатор этой записи , а затем выпустить UPDATE car_owners_cross SET owner_id=123, car_type_id=456 WHERE id=789
- но я не знаюкак получить идентификаторДля этой записи
Примечания:
- существуют планы для новой функции, которая значительно усугубит проблему (создание и удаление тонны записейРегулярно, много раз без толку - пока пользователь просто «играет с настройками», оставляя лишь несколько не
deleted
записей после - так что было бы очень полезно иметь такую функцию с самого начала - в приведенном выше примере - каждый владелец может иметь любое количество типов автомобилей (и любое количество идентичных типов автомобилей - поэтому многие записи будут иметь одинаковые значения, кроме уникального идентификатора), а также любой CarType может принадлежать любому количеству владельцев
- реальные записи намного сложнее, но принцип тот же
- количество (
deleted
) записей уже создает проблемы - цель состоит в том, чтобы улучшить соотношение
valid
к deleted
записей, а не в том, чтобы исключать каждую «удаленную» запись (чтобы можно было сохранить пул reuse_me
отмеченных записей, чтобы быть уверенным, что UPDATE
получит свою жертву и сделает новые записи, даже если некоторые reuse_me
все еще существуют - размер пула может быть настроен в коде, просто нужно быть "вменяемым" - скажем, как 3-кратное число ожидаемых одновременно вошедших в систему пользователей иличто-то в этом роде - есть возможность добавлять другие поля в затронутые таблицы, поддерживать
reuse_me
или делать reuse_me
любого другого типа, кроме логического - , не все создание новой записи будетиспользуйте эту возможность (например, интерфейс администратора все равно будет просто использовать
INSERT
(coc=Car_Owners_Cross();...;coc.save();
) и некоторые старые инструменты тоже) - если эта функция будет использоваться, все значения по умолчанию могут быть "вручную" установлены с помощью кодак допустимым значениям (было бы неплохо иметь их в значениях по умолчанию (просто для большей безопасности - но не совсем запрошено)
- не все таблицы будут использоваться таким образом (и только таблицы из нашей ауn моделей будет, так что без аутентификации. * и т. д.)