Как обеспечить согласованность данных
Приложение C#.
Я делаю выбор с последующим обновлением столбца в таблице. Я помещаю их в отдельную транзакцию с уровнем изоляции, установленным в Serializable. Я делаю это для достижения согласованности данных.
Но все же я могу проверить, что несколько пользователей могут прочитать (выбрать) одно и то же значение и в конечном итоге пытаются обновить с одним и тем же значением.
Может ли кто-нибудь предложить, как я могу добиться последовательности, так что
Нет двух пользователей, читающих одно и то же значение.
Ни один пользователь не прочитал значение, которое обновлено, но еще не зафиксировано.
6 ответов
Если вы хотите предотвратить это, это называется пессимистической блокировкой. Вы можете сделать это с помощью (Table|Row) блокировок, но это снизит вашу производительность.
"Стандартный" способ - использовать оптимистичный параллелизм и решать проблему после ее возникновения.
Нет двух пользователей, читающих одно и то же значение.
Вы можете (только) убедиться в этом, разрешив только 1 соединение одновременно.
Ни один пользователь не прочитал значение, которое обновлено, но еще не зафиксировано.
Для этого требуется только (намного более легкий) уровень изоляции ReadCommitted.
Есть много разных способов добиться этого. Вы можете использовать метки времени в своих записях. Когда вы делаете обновление, вы удостоверяетесь, что идентификатор совпадает и отметка времени, которую ваше приложение извлекло с записью, совпадает.
Чтобы пользователь не читал записи, которые не были переданы, используйте SQL-подсказки в своих запросах.
Я думаю, что вы имеете в виду параллелизм. Проверьте ссылку, чтобы начать понимать ее, если это то, о чем вы спрашиваете. Вам, вероятно, придется сделать немного больше исследований в зависимости от вашей серверной части и вашей конкретной ситуации. Опять же, если это то, что вы ищете, вас может заинтересовать пессимистический параллелизм.
http://en.wikipedia.org/wiki/Concurrency_control
Обработка проблем параллелизма в.NET
Как насчет размещения обновления с возвратом в обработанный процесс и вызовом его из моего приложения.
Это позаботится обо всех проблемах?
Нет двух пользователей, читающих одно и то же значение.
Для этого в своем выражении SET TRANSACTION добавьте RESERVING mytable FOR PROTECTED WRITE (или локальный эквивалент в вашей базе данных).
Ни один пользователь не прочитал значение, которое обновлено, но еще не зафиксировано.
Если вы используете SERIALIZABLE транзакции, у вас не будет этой проблемы.
Один из способов выполнить задачу: вам нужно добавить поле "блокировка" в вашу таблицу.
затем вы должны написать хранимую процедуру, которая будет принимать некоторый идентификатор в качестве параметра, атомарно выбрать строку с блокировкой NULL, обновить строку таким образом, чтобы блокировка содержала переданный идентификатор, а затем вернуть значение.
Пока хранимая процедура выполняется атомарно (любые другие запросы для таблицы будут ждать до тех пор, пока эта процедура не будет завершена), каждый клиент, вызывающий эту процедуру, получит другое значение, в котором поле блокировки все еще не заполнено. Как только значение возвращается, клиент уверен, что строка, содержащая значение, имеет свое поле блокировки, установленное в какое-либо значение, и не будет возвращено.
После внесения изменений вы должны обновить строку, записать новое значение и установить для поля блокировки значение NULL, тем самым "разблокировав" строку для будущих запросов.