Редактирование записей базы данных несколькими пользователями - PullRequest
26 голосов
/ 04 августа 2008

Я спроектировал таблицы базы данных (нормализовано на сервере MS SQL) и создал автономный интерфейс Windows для приложения, которое будет использоваться несколькими пользователями для добавления и редактирования информации. Мы добавим веб-интерфейс, который позволит выполнять поиск по всей производственной области позднее.

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

  1. Ничего не делайте и надейтесь, что два пользователя никогда не будут редактировать одну и ту же запись одновременно. - Может никогда не случится, но что, если это произойдет?
  2. Подпрограмма редактирования может сохранять копию исходных данных, а также обновления, а затем сравнивать, когда пользователь закончит редактирование. Если они отличаются, покажите обновление пользователя и подтверждения - потребуется две копии данных для хранения.
  3. Добавить последний обновленный столбец DATETIME и проверить, совпадает ли он при обновлении, если нет, то показать различия. - требуется новый столбец в каждой из соответствующих таблиц.
  4. Создание таблицы редактирования, которая регистрируется, когда пользователи начинают редактировать запись, которая будет проверяться, и не позволяет другим пользователям редактировать ту же запись. - потребовалось бы тщательно продумать ход выполнения программы, чтобы предотвратить блокировку взаимоблокировок и записей в случае сбоя пользователя из программы.

Есть ли лучшие решения или я должен пойти на один из них?

Ответы [ 8 ]

14 голосов
/ 04 августа 2008

Если вы ожидаете нечастых столкновений, Оптимистичный параллелизм , вероятно, является вашей лучшей ставкой.

Скотт Митчелл написал подробное руководство по реализации этого шаблона:
Реализация оптимистического параллелизма

2 голосов
/ 01 октября 2008

Классический подход заключается в следующем:

  • добавить логическое поле, «заблокированное» для каждой таблицы.
  • по умолчанию установлено значение false.
  • когда пользователь начинает редактирование, вы делаете это:

    • заблокировать строку (или всю таблицу, если вы не можете заблокировать строку)
    • отметьте флаг в строке, которую вы хотите редактировать
    • если флаг имеет значение true, тогда
      • сообщить пользователю, что он не может редактировать эту строку в данный момент
    • еще
      • установить флаг в true
    • снять блокировку

    • при сохранении записи установите флаг обратно в false

1 голос
/ 14 июля 2016

- первое создание поля (время обновления) для сохранения последней записи обновления - когда любой пользователь выбирает запись, сохраняет время выбора, сравнить между временем выбора и полем обновления, если (время обновления)> (время выбора) означает, что другой пользователь обновил эту запись после записи выбора

1 голос
/ 01 октября 2008

ВЫБРАТЬ ДЛЯ ОБНОВЛЕНИЯ и эквиваленты хороши, если вы держите блокировку в течение микроскопического промежутка времени, но для макроскопического количества (например, пользователь загрузил данные и не нажал «сохранить», вы должны использовать оптимистичный параллелизм, как указано выше (Который я всегда считаю неверным - он более пессимистичен, чем «последний писатель выигрывает», что обычно является единственной альтернативой.)

1 голос
/ 14 августа 2008

Другой вариант - проверить, что значения в изменяемой записи остаются такими же, какими они были при запуске:

SELECT 
    customer_nm,
    customer_nm AS customer_nm_orig
FROM demo_customer
WHERE customer_id = @p_customer_id

(отобразить поле customer_nm и пользователь изменяет его)

UPDATE demo_customer
SET customer_nm = @p_customer_name_new
WHERE customer_id = @p_customer_id
AND customer_name = @p_customer_nm_old

IF @@ROWCOUNT = 0
    RAISERROR( 'Update failed: Data changed' );

Вам не нужно добавлять новый столбец в вашу таблицу (и поддерживать его в актуальном состоянии), но вы должны создавать более подробные операторы SQL и передавать new и old полей для хранимой процедуры.

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

1 голос
/ 05 августа 2008

@ Марк Харрисон: SQL Server не поддерживает этот синтаксис (SELECT ... FOR UPDATE).

Эквивалентом SQL Server является подсказка SELECT UPDLOCK.

См. Электронная документация по SQL Server для получения дополнительной информации.

0 голосов
/ 24 июня 2011

Со мной лучше всего использовать столбец lastupdate (timetamp datatype). при выборе и обновлении просто сравните это значение Еще одним преимуществом этого решения является то, что вы можете использовать этот столбец для отслеживания времени изменения данных. Я думаю, это нехорошо, если вы просто создадите столбец, например isLock, для проверки обновлений.

0 голосов
/ 04 августа 2008

База данных сделает это за вас. Посмотрите на "выбрать ... для обновления", который предназначен именно для такого рода вещей. Он предоставит вам блокировку записи для выбранных строк, которую вы затем сможете зафиксировать или откатить.

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