Как не превысить максимально допустимое количество Photos в таблице базы данных с одинаковым albumID?
Извиняюсь за плохо переданную "суть вопроса".
Есть сущности Альбом и Фото.
Фото хранятся не в коллекции альбома, а отдельно. Фото содержит id альбома(albumID), это единственная связь между альбомом и фотографиями.
Есть задача: не превысить число фотографий в альбоме. То есть нужно следить за тем, чтобы фотографий, у которых, например, albumID === 123, в базе данных не перевалило за сотню. А такой исход возможен при таком сценарии: в альбоме уже 99 фото, паралельно выполняются 2 запроса на добавление фото в этот альбом. Сначала первый процесс смотрит, что количество фотографий равно 99 и создаёт новое Фото. Затем второй процесс смотрит, что количество фотографий всё ещё равно 99(первый процесс еще не сохранил фото) и также создаёт новое Фото, затем процессы по очереди сохраняют созданные фото в БД и получается, что в альбоме уже 101 фотография.
(Стоит заметить, что я хочу, чтобы в данном use case создавалось фото, но не происходили изменения в альбоме, то есть Album::photosCount инкрементиться не будет).
Здесь не помогут оптимистическая и пессимистическая блокировки, потому что ничего не изменяется, только создаётся. Может помочь запрет на чтение количества фотографий, чтобы второй процесс ждал пока первый процесс не закончится, чтобы он смог прочитать обновленное количество фото, но не знаю правильно ли это. Или каким-то образом сделать ограничение в базе данных, чтобы небыло больше 100 одинаковых значений в колонке "albumID" в таблице с фотографиями.
Я не нашёл решения в интернете, наверное, потому что в основном все используют коллекции и lazy load, в таком случае очень легко соблюдать инварианты. Но для больших проектов такой подход не уместен(вроде бы) из-за проблем связанных с увеличением количества записей и масштабированием. Естественно мне это сейчас не нужно, просто хочу знать оптимальное решение.
Я бы и не думал о решении на уровне базы данных, но я не могу придумать решение с помощью бизнес логики, поэтому и спрашиваю. Я отбросил решение на уровне БД. Есть идеи какие-то?
Алексей Потапенко, правда 100% гарантии не существует, поэтому если хочется такое то придется добавлять обработчик с аудитом, который будет ходить и смотреть за тем не превысил ли кто чего
Как не превысить максимально допустимое количество 100
Не записывать 101-ую. Например, составной уникальный ключ: код альбома, номер. Нумеровать последовательно. Если одновременно добавляется, то кто первый завершит транзакцию, того и тапки — другому ошибка.
Мне уже предлагали такое решение. Но не всё так просто. Допустим есть альбом с id 13 и в этом альбоме уже 100 фотографий. Кто-то удаляет фото с составным ключом 88_13(где 13 - id альбома). Теперь в альбоме 99 фото. Затем кто-то решает добавить фото в этом альбом. Берём количество(99), инкрементим, и добавляем id альбома, получится 100_13, сохрянем это фото и получаем ошибку, потому что в таблице уже есть альбом с таким составным ключом. Чтобы такого не случилось, нужно при удалении фотографии с составным ключом 88_13 сразу пройтись по фотографиям начиная от 89_13 и заканчивая 100_13 и отнимать от номера(левая часть ключа) единицу. То есть смещаем составные ключи на единицу вниз, чтоб заполнить пустоту после удаления фото. Или взять последнее фото, то есть 100_13 и сделать его 89-ым. Но мне кажется, что у такого способа есть ещё недостатки, просто я их пока не заметил.