Редактирование записей базы данных несколькими пользователями

StackOverflow https://stackoverflow.com/questions/833

  •  08-06-2019
  •  | 
  •  

Вопрос

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

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

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

Есть ли какие-то лучшие решения или мне следует выбрать одно из них?

Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

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

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

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

Видишь Книги по SQL Server Онлайн для получения дополнительной информации.

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

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

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 и передать новое и Старый поля для хранимой процедуры.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top