Как гарантировать ограничение между строками SQL? - PullRequest
0 голосов
/ 24 августа 2011

Мы разрабатываем приложение онлайн-графика. Одно расписание может редактироваться одновременно несколькими пользователями. Есть одно очень важное деловое ограничение. Там должно быть только три события в один день.

Технически говоря и упрощенно, в базе данных есть таблица со столбцами: | id | событие | дата | Приложение запускается в транзакции "select ... count ... where ..." и, если результат меньше 3, оно вставляет новое событие.

Какие подходы можно использовать, чтобы гарантировать, что два потока не создадут четыре события за один день? Это классическая проблема проверки и записи. И нам интересно, как это можно решить на уровне базы данных?

Использование транзакций не гарантирует, что во второй транзакции другой поток не будет делать то же самое: проверяет, что число событий меньше 3, и выполняет вставку. Блокировка всей таблицы недопустима, поскольку она сократит время отклика, параллелизм и т. Д.

Приложение разработано на Java с использованием Spring, Hibernate, MySQL.

Заранее благодарим за любые советы.

Ответы [ 3 ]

0 голосов
/ 24 августа 2011

Для блокирования процесса вы должны использовать оператор Select ... FOR UPDATE. Но этот работает только в innodb.

Пример:

//java logic
try {
    //mysql logic
    start transaction;
    select * from where 'some condition' FOR UPDATE
    INSERT INTO TABLE ....    
    commit;
//java logic
catch (Exception e) {
    rollback;
}

Подробнее о блокировке отдельных строк http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html

0 голосов
/ 24 августа 2011

Поскольку вы проходите через Spring и из-за проблем с параллелизмом попробуйте синхронизировать выполнение на уровне Java, а не на уровне DB.У нас были похожие проблемы при попытке использовать БД для поддержки параллелизма.

Возможно, вы могли бы сделать блок выполнения в Java synchronized так, чтобы он принудительно блокировал выполнение;внутри синхронизированного метода проверьте, что вся ваша бизнес-логика возвращает true.если истина, продолжите нормальное выполнение.Если false, прервать с исключением.

0 голосов
/ 24 августа 2011

В вашей модели данных вы можете использовать проверочное ограничение для подсчета количества строк. AFAIK MySQL изначально не поддерживает этот тип ограничений, но, похоже, можно эмулировать их с помощью триггера

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

...