Предпочтительный дизайн параллельной работы базы данных / веб-приложения, когда несколько пользователей могут редактировать одни и те же данные - PullRequest
8 голосов
/ 07 мая 2009

У меня есть бизнес-приложение ASP.NET C # для внутреннего использования. Одна проблема, с которой мы сталкиваемся по мере роста, заключается в том, что оригинальный дизайн не учитывал проверку параллелизма - поэтому теперь несколько пользователей получают доступ к одним и тем же данным и перезаписывают изменения других пользователей. Поэтому мой вопрос - для веб-приложений люди обычно используют пессимистическую или оптимистическую систему параллелизма? Что движет предпочтением использовать один над другим, и что нужно учитывать при проектировании?

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

Спасибо!

Ответы [ 4 ]

3 голосов
/ 07 мая 2009

Я согласен с первым ответом выше, мы пытаемся использовать оптимистическую блокировку, когда вероятность столкновений довольно мала. Это можно легко реализовать с помощью столбца LastModifiedDate или путем увеличения столбца версии. Если вы не уверены в частоте столкновений, регистрируйте события где-нибудь, чтобы вы могли следить за ними. Если ваши записи всегда находятся в режиме «редактирования», наличие отдельных режимов «просмотра» и «редактирования» может помочь уменьшить коллизии (при условии, что вы перезагружаете данные при входе в режим редактирования).

Если коллизии все еще высоки, пессимистическая блокировка труднее реализовать в веб-приложениях, но определенно возможна. Мы добились больших успехов с «сдачей в аренду» записей (блокировка с тайм-аутом) ... аналогично тому 2-минутному предупреждению, которое вы получаете при покупке билетов на TicketMaster. Когда пользователь переходит в режим редактирования, мы помещаем запись в таблицу «lock» с таймаутом N минут. Другие пользователи увидят сообщение, если они попытаются отредактировать запись с активной блокировкой. Вы также можете внедрить поддержку активности для длинных форм, обновив аренду для любой обратной передачи страницы или даже с помощью таймера AJAX. Нет также причины, по которой вы не могли бы подтвердить это стандартной оптимистической блокировкой, упомянутой выше.

Многим приложениям потребуется сочетание обоих подходов.

3 голосов
/ 07 мая 2009

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

Вы не указываете, какую базу данных вы используете. Сервер MS SQL имеет тип данных временной метки. Это не имеет ничего общего со временем, хотя. Это просто число, которое будет меняться при каждом обновлении строки. Вам не нужно ничего делать, чтобы убедиться, что оно изменилось, вам просто нужно это проверить. Вы можете добиться аналогичных результатов, используя дату / время, которые были изменены в последний раз, как предполагает @KM. Но это означает, что вы должны помнить, чтобы изменить его каждый раз, когда вы обновляете строку. Если вы используете datetime, вам нужно использовать тип данных с достаточной точностью, чтобы гарантировать, что вы не сможете получить значение, не меняющееся, когда оно должно. Например, кто-то сохраняет строку, затем кто-то читает ее, затем происходит другое сохранение, но оставляет измененную дату / время без изменений. Я использовал бы метку времени, если не было необходимости отслеживать дату последнего изменения в записях.

Чтобы проверить это, вы можете сделать так, как подсказывает @KM, и включить его в предложение update where. Или вы можете начать транзакцию, проверить метку времени, если все в порядке, а затем зафиксировать транзакцию, если нет, вернуть код ошибки или ошибку.

Удержание открытых транзакций (как предлагает @le dorfier) ​​похоже на пессимистическую блокировку, но объем заблокированных данных может превышать строку. Большинство RDBM блокируется на уровне страницы по умолчанию. Вы также столкнетесь с теми же проблемами, что и с пессимистической блокировкой.

Вы упоминаете в своем вопросе, что беспокоитесь о конфликтующих обновлениях. Это то, что блокировка обязательно предотвратит. И оптимистическая, и пессимистическая воля при правильном применении предотвратят именно это.

1 голос
/ 07 мая 2009

вот простое решение для многих людей, работающих над одинаковыми записями.

когда вы загружаете данные, получаете дату последнего изменения, мы используем LastChgDate для наших таблиц

когда вы сохраняете (обновляете) данные, добавьте «AND LastChgDate = предыдущийLoadedLastChgDate» в предложение where. Если при обновлении количество строк = 0, выведите ошибку, когда «кто-то другой уже сохранил эти данные» и откатите все, иначе данные будут сохранены.

Обычно я делаю вышеуказанную логику только для таблиц заголовков, а не для таблиц сведений, поскольку все они находятся в одной транзакции.

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

Я полагаю, у вас проблема с "потерянным обновлением".

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

Тебе действительно нужно увидеть, что относится к твоей ситуации, и сделать суждение.

...