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

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

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

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

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

3.08.2008 21:23:41
8 ОТВЕТОВ
РЕШЕНИЕ

Если вы ожидаете нечастых столкновений, возможно, вам лучше всего использовать Optimistic Concurrency .

Скотт Митчелл (Scott Mitchell) написал всеобъемлющее руководство по реализации этого шаблона:
реализация оптимистического параллелизма

15
28.01.2013 04:20:13

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

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

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

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

3
1.10.2008 08:53:19
Это не очень хорошо, если установить lock = true, если приложение или браузер аварийно завершают работу, то запись навсегда заблокирована.
Cheung 29.11.2010 20:12:16
Хороший вопрос, @SilverNight - вы можете опубликовать правильное решение?
AJ. 30.11.2010 10:30:33
В таких случаях (сбой приложения / браузера) вы можете добавить в приложение метод ForceUnlock, который принудительно установит блокировку на False.
Oleksandr 17.08.2014 05:39:17
Эта волна,
Chris Marisic 3.10.2014 19:04:05

SELECT FOR UPDATE и их эквиваленты хороши, если вы держите блокировку в течение микроскопического промежутка времени, но для макроскопического количества (например, пользователь загрузил данные и не нажал «сохранить», вы должны использовать оптимистичный параллелизм, как указано выше. (Который Я всегда думаю, что это неправильно названо - это более пессимистично, чем «последний писатель выигрывает», что обычно является единственной альтернативой.)

1
1.10.2008 05:39:22

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

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

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

1
5.06.2015 05:56:44

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

1
14.07.2016 11:23:05

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

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

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

1
8.02.2018 10:56:35

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

0
4.08.2008 02:30:09

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

0
24.06.2011 07:14:00