Я занимаюсь дизайном аукциона, например, с помощью Rails 3.1 и MySQL 5.1. У пользователей будет баланс по счету, поэтому важно, чтобы кто-то не предлагал цену за предмет аукциона, если у него недостаточно средств.Оптимистичная или пессимистическая блокировка в аукционном/банковском приложении (Rails/MySQL)
Очевидно, я буду паковать «победы» аукциона в сделку, выходит что-то вроде этого:
Сделка 1:
ActiveRecord::Base.transaction do
a = Account.where(:id=>session[:user_id]).first
# now comes a long part of code with various calculations and other table updates, i.e. time pases
a.balance -= the_price_of_the_item
a.save!
end
Кстати, я curerntly используя оптимистическую блокировку, следовательно, все мои таблицы имеют lock_version столбца.
Хотя такая транзакция выполняется, пользователь может через другой входной место другие предложения, поэтому всякий раз, когда они сделать ставку, кусок кода проверяет, если текущий доступный остаток достаточно
То же самое и здесь:
сделка 2:
ActiveRecord::Base.transaction do
a = Account.where(:id=>session[:user_id]).first
raise ActiveRecord::Rollback if a.balance < the_price_of_the_bid + Bids.get_total_bid_value_for_user(session[:user_id])
# now process the bid saving
end
Очевидно мне нужно убедиться, что эти две операции не перекрывают друг друга, в противном случае сделка 2 может читать баланс в то время как сделка 1 находится в центре обработки и я в конечном итоге с h отрицательный остаток на счете (ставка сохраняется, а затем транзакция 1 совершает, тогда у пользователя есть возможность делать ставки за счет средств, которых у него больше нет).
Следует отметить, что транзакция 2 не вносит никаких изменений в Учетную запись, она просто считывает учетную запись. Я думаю, это сводится к вопросу: как предотвратить любые чтения для выбранных операторов SELECT во время выполнения транзакции.
Как сделать транзакцию 2 дождаться завершения транзакции 1? Возможно ли это с оптимистичной блокировкой и одним из доступных уровней изоляции транзакций MySQL или мне нужно использовать пессимистическую блокировку здесь? Если пезимистическая блокировка является единственным ответом, добавив a.lock! после прочтения записи учетной записи в каждой из двух транзакций достаточно?
Дизайн критерии, конечно
- Ищу наиболее производительным решения, даже если это означает более кодирования.
- непротиворечивость данных имеет первостепенное значение
Просто попытайтесь понять ваши данные. Скажите, что у кого-то есть баланс 10. Могут ли они создать 2 ставки по 10 каждый (на данный момент мы не знаем, выиграет ли кто-нибудь или кто-нибудь выиграет)? Если они не могут, как вы это отслеживаете? –
Нет, они не могут, в противном случае я рискую, что они выиграют обе ставки, и это приведет к балансу -10 на их счетах. Отслеживание выполняется в транзакции 2, оно проверяет доступный баланс, и только у пользователя достаточно денег на счете, тогда его ставка будет принята и сохранена. – KKK
Так что код также идет и проверяет, есть ли в настоящее время открытые ставки? (или отражает баланс счета) –