Назначение задач ввода данных нескольким одновременным пользователям веб-приложений - PullRequest
0 голосов
/ 31 мая 2009

Я пытаюсь придумать эффективный способ, позволяющий группе людей работать через очередь задач ввода данных. Ранее у нас только один человек делал это, так что это не было проблемой. Back-end - это RDBMS, а front-end - это веб-приложение.

В настоящее время мы делаем что-то вроде этого:

Чтобы назначить запись для редактирования:

SELECT * FROM records WHERE in_edit_queue LIMIT 1;

Тогда

Чтобы сохранить изменения в ранее назначенной записи:

UPDATE records SET ..., in_edit_queue = false
  WHERE id = ? AND in_edit_queue = true;

Это означает, что двум пользователям может быть назначено редактировать одну и ту же запись, и мы отдаем предпочтение первой, которая подает заявку, молча терпя неудачу при последующих отправках, например ::

  1. Пользователь A загружает запись 321 для редактирования
  2. Пользователь B загружает запись 321 для редактирования
  3. Пользователь Б отправляет изменения (они сохраняются в БД)
  4. Пользователь A отправляет изменения (они не сохраняются в БД)

(Примечание. Мы можем доверять всем нашим пользователям предоставление приемлемых данных, поэтому нам не нужно хранить данные со второго UPDATE.)

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

Так вот что я думаю ...

Иметь таблицу под названием: locked_records (record_id integer, locked_until timestamp)

-- Assign a record for editing:
-- Same as before but also make sure the
-- record is not listed in locked_records...
SELECT * FROM records
  WHERE in_edit_queue AND id NOT IN (
    SELECT record_id FROM locked_records
    WHERE locked_until > now() )
  LIMIT 1;

-- ..and effectively remove it from
-- the queue for the next 5 minutes
INSERT INTO locked_records (record_id, locked_until)
  VALUES (?, now() + 300);

Тогда:

UPDATE records SET ..., in_edit_queue = false
  WHERE id = ? AND in_edit_queue = true;
DELETE FROM locked_records WHERE record_id = ?;

Типичное редактирование занимает от 30 секунд до 1 минуты, 5 минут из очереди должно быть хорошей суммой. У меня также может быть XHR в веб-приложении, которое постоянно обновляет блокировку, если она оказалась выгодной.

Может кто-нибудь предложить мысли по этому поводу? Звучит как хороший способ делать вещи? Звучит как ужасный путь? Сделано это раньше? Я хотел бы услышать некоторые отзывы.

Спасибо! J

Ответы [ 2 ]

0 голосов
/ 31 мая 2009

Другая идея: у этих записей есть два дополнительных столбца: assign_to и complete.

Когда кто-то хочет отредактировать запись, сделайте что-то вроде

update records set assigned_to = ? # assigning to 'me'
where assigned_to is null
and completed = false
limit 1 # only assign one record at a time

Затем, чтобы вернуть этот ряд:

select ...
from records
where assigned_to = ? # assigned to 'me'
and completed = false

И как только вы закончите, вы установите для «true» значение «true».

У вас может быть дополнительный столбец отметки времени, когда кому-то была назначена запись, а затем добавить альтернативу OR к части "assign_to is null" в предложении where в приведенном выше операторе update, где вам требуется определенное получение назначение должно быть действительным.

0 голосов
/ 31 мая 2009

А как насчет внутреннего списка блокировок СУБД? Будет ли изменение оператора SELECT на SELECT FOR UPDATE вариант?

...