Scala Асинхронные вызовы базы данных
В настоящее время я использую Slick 3.xx, который полностью асинхронный во всех своих обращениях к базе данных. Допустим, у меня есть таблица, которая имеет какое-то управление версиями. Каждый раз, когда я создаю новую запись из уже существующей записи (т.е. обновляю данную запись), я должен убедиться, что я увеличиваю номер версии.
Как я могу убедиться в этом асинхронном мире связи с базами данных, что я могу поддерживать целостность данных? В моем случае с версионированием я сначала сделал бы выбор для максимальной версии, который вернул бы мне Future, а затем я использовал результат этого Future, инкремент 1 и выполнил команду create!
Вполне возможно, что поток 1 запускается с select max version и приостанавливается на некоторое время, а поток 2, обслуживающий новый запрос, может запустить select for max version и increment и записать новую запись в базу данных. Теперь поток 1 возвращается и пытается выполнить тот же процесс, но только для того, чтобы поток 1 перезаписал то, что поток 2 записал в базу данных.
Может случиться так, что я получу несколько дубликатов, потому что порядок запуска нескольких фьючерсов может отличаться!
1 ответ
Асинхронность, с которой ваше приложение управляет взаимодействием с базой данных, не меняет семантику транзакций базы данных. если вам нужны атомарные согласованные последовательности операций, то вам нужна транзакция базы данных. Слик предлагает "комбинатор" под названием transactionally
что заставит последовательность операций выполняться внутри транзакции базы данных.