Сведения о вопросе

Kimsanov

16:03, 1st July, 2020

Теги

sql-server   database    

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

Просмотров: 479   Ответов: 8

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

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

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

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



  Сведения об ответе

+-*/

18:03, 1st July, 2020

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

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


  Сведения об ответе

pumpa

18:03, 1st July, 2020

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

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

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

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


  Сведения об ответе

ASSembler

18:03, 1st July, 2020

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

Эквивалентом SQL сервера является SELECT оператор hint UPDLOCK .

Дополнительную информацию смотрите в разделе SQL Server Books Online .


  Сведения об ответе

прога

18:03, 1st July, 2020

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

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

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


  Сведения об ответе

lourence

18:03, 1st July, 2020

Выберите для обновления и эквиваленты хороши, если вы держите блокировку в течение микроскопического количества времени, но для макроскопического количества (например, пользователь загрузил данные и не нажал 'save') вы должны использовать оптимистичный параллелизм, как описано выше. (Который я всегда считаю неправильным названием - Он более пессимистичен, чем "последний писатель выигрывает", который обычно является единственной альтернативой, рассматриваемой.)


  Сведения об ответе

repe

18:03, 1st July, 2020

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


  Сведения об ответе

lool

18:03, 1st July, 2020

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


  Сведения об ответе

lourence

18:03, 1st July, 2020

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться