Блокировка выбора в Rails с MySQL - PullRequest
5 голосов
/ 17 августа 2010

Нужен совет по передовому опыту:

Предположим, у меня есть объект Account с атрибутом limit. Каждый день может быть n платежей, с суммой их сумм вплоть до лимита счета. При создании нового платежа он проверяет, находятся ли его сумма + суммы других платежей за день в пределах лимита учетной записи, и либо сохраняет запись, либо отображает ошибку.

Теперь предположим, что у меня есть аккаунт с лимитом 100 $, и одновременно создаются два платежа по 99 $. Каждый будет делать выбор, видеть, что там ничего нет, и приступать к самосохранению, в результате чего будет сохранено всего 198 $.

Что бы вы сделали с этим? Я думал о том, чтобы установить блокировку записи в таблице платежей в начале транзакции, но это выглядит довольно жестко, поскольку я действительно беспокоюсь о том, чтобы не допустить, чтобы платежи, принадлежащие определенному аккаунту, не читались другими транзакциями. Есть ли другие варианты, лучшие способы справиться с этой ситуацией?

Ответы [ 2 ]

3 голосов
/ 17 августа 2010

Я думал о блокировке записи в таблице платежей в начале транзакции, но кажется, что она слишком сложна

Предполагая, что вы уже говорите о транзакциях, яЯ предполагаю, что вы не используете MyISAM, но вместо этого InnoDB или какой-то другой движок, который уже поддерживает транзакции.

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

Для описанного вами варианта использования вы хотите, чтобы транзакции были транзакциямис уровнем изоляции SERIALIZABLE, который блокирует чтение и запись.Кроме того, он автоматически блокирует только те записи, из которых вы прочитали (даже если вы запрашиваете диапазоны), поэтому оставшиеся записи свободны для манипуляций.

Через уровень изоляции «SERIALIZABLE», моментЕсли вы читаете информацию из таблицы, любые попытки обновить или прочитать эти записи должны будут ждать завершения этой транзакции.Кроме того, убедитесь, что вы прочитали перед обновлением той же транзакции, чтобы убедиться, что вы работаете с правильным значением.

Подробнее об уровнях изоляции можно прочитать здесь: http://en.wikipedia.org/wiki/Isolation_(database_systems) http://www.databasejournal.com/features/mysql/article.php/3393161/MySQL-Transactions-Part-II---Transaction-Isolation-Levels.htm

Вы можете узнать, как настроить уровень изоляции ваших транзакций здесь: http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html

1 голос
/ 17 августа 2010
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...