Как лучше всего (в Rails / AR) обеспечить синхронную запись в таблицу базы данных, одну за другой, одну за другой? - PullRequest
0 голосов
/ 23 декабря 2011

Я заметил, что использование чего-то вроде delayed_job без ограничения UNIQUE для столбца таблицы будет по-прежнему создавать двойные записи в БД.Я предполагал, что delayed_job будет запускать задания один за другим.Приложение Rails работает на Apache с Passenger Phusion.Я не уверен, является ли это причиной того, что это произошло, но я хотел бы убедиться, что каждый элемент в очереди сохраняется в AR / DB один за другим, последовательно, и чтобы никогда не было более одной записи в этоБД таблицы бывают одновременно.Это возможно?С какими проблемами мне придется столкнуться?

update

Условия гонки возникают из-за того, что для отправки данных в приложение используется API AJAX.Приложение получило набор данных, каждый пакет данных идентифицируется как принадлежащий друг другу с помощью идентификатора сеанса (SID), в конце концов, конечное состояние базы данных должно включать в себя самый последний самый актуальный запрос AJAX PUT кAPI.Иногда запросы поступают в одно и то же время для одного и того же SID - поэтому мне нужен способ убедиться, что они не все пытаются быть сохранены в одно и то же время, а один за другим, или просто последний, который будет отправленAJAX-запрос к API.

Надеюсь, это облегчит понимание моего конкретного варианта использования ...

Ответы [ 2 ]

0 голосов
/ 23 декабря 2011

Если вас беспокоит / беспокоит / из-за того, что несколько процессов записывают в «одинаковые» строки - как у большего количества пользователей, обновляющих одну и ту же строку order_header - я бы посоветовал вам один раз установить маркер, привязанный к current_user.id в строке / order_headers /: id / edit был вызван и снова удален, когда current_user освобождает строку, обновляя или отменяя редактирование.

Ваш вариант использования (из вашего описания) мне кажется немного другим, поэтому я бы посоветовал вам оставить его в БД (в случае довольно недавнего - как в посте 5.1 - MySQL, вы бы добавили триггер / функция, которая будет выполнять фактическое обновление, и здесь - вы можете реализовать логику, аналогичную приведенной выше; некоторый маркер привязан к определенному последовательному идентификатору задания)

0 голосов
/ 23 декабря 2011

Вы можете заблокировать определенную таблицу (или таблицы) с помощью оператора LOCK TABLES.

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

С вашими дальнейшими объяснениями я бы соблазнился добавить несколько дополнительных столбцов в таблицу, используемую delayed_job, с уникальным индексом для них. Если (например) вы когда-либо хотели получить только 1 задание на пользователя, добавьте столбец user_id, а затем выполните

something.delay(:user_id => user_id).some_method

Вам может понадобиться больше атрибутов, если шаблон более сложный, например, Есть много разных типов рабочих мест, и вы хотели только одну на человека, на тип, но принцип тот же. Вы также хотели бы быть в состоянии спасти ActiveRecord::RecordNotUnique и изящно справиться с этим.

Для вещей, не относящихся к delayed_job, оптимистическая блокировка часто является хорошим компромиссом между хорошей обработкой параллельных случаев без замедления непоследовательных случаев.

...