Какая минимальная изоляция требуется, чтобы гарантировать, что только один SQL UPDATE внес изменения? - PullRequest
2 голосов
/ 02 марта 2012

Вот команда SQL UPDATE с параметрами ...

UPDATE MyTable 
SET MyField = @newvalue, 
    @success = 1
WHERE 
    Id = @id 
    AND MyField = @oldvalue

Многие клиенты будут запускать эту команду с одинаковыми значениями параметров @id и @oldvalue одновременно. Я хочу, чтобы только один из них был «победителем» и установил MyField на свой собственный @newvalue, и чтобы он знал, что он выиграл, потому что выходной параметр @success будет установлен в 1.

Какой самый низкий уровень изоляции необходим для того, чтобы это работало и гарантировало, что только один клиент когда-либо «победит»? Нужна ли транзакция для этого одного заявления?

Я использую SQL Server 2008, но надеюсь, что есть стандартный ответ SQL.

Ответы [ 3 ]

2 голосов
/ 02 марта 2012

Оператор SQL Server UPDATE будет всегда ставить (U) (блокировку обновления) во время фазы чтения обновления, которая затем преобразуется в (X) (эксклюзивная блокировка) для фактический процесс записи новых значений в строку (или страницу / таблицу), которую вы обновляете, независимо от того, какой уровень изоляции транзакции вы используете.

Поскольку одна (U) блокировка несовместима с другой (U) блокировкой на том же уровне, если один процесс уже имеет (U) блокировку, никакое другое соединение не может запустить UPDATE одновременно и должно будет ждать.

Опять же: это стандартное поведение для SQL Server - независимо от того, какой уровень изоляции транзакций вы используете - оно одинаково для всех этих уровней изоляции.

Я не знаю, действительно ли это утверждение для других систем РСУБД - скорее всего, нет. Подобные вещи не обрабатываются никаким стандартом ANSI SQL - они всегда сильно зависят от поставщика.

2 голосов
/ 02 марта 2012

При условии, что новое значение всегда отличается от старого, достаточно уровня изоляции по умолчанию, READ COMMITTED.

Однако, если значение может оказаться таким же, как старое значение,клиенты преуспеют.Один за другим.И у каждого будет @success = 1.

0 голосов
/ 03 апреля 2012

Поведение SQL Server было рассмотрено, но я расширю часть вопроса о «стандартном ответе SQL».

Я не знаю ни одной СУБД, которая требовала бы более строгой изоляцииуровня чем READ COMMITTED, чтобы получить запрашиваемое вами поведение, при условии (как уже упоминалось), что новое значение отличается от старого значения.Я считаю, что требования различных уровней изоляции транзакций в стандарте SQL должны гарантировать это для любого соответствующего продукта базы данных.Это не всегда обеспечивается типами блокировок, описанными в других ответах, но большинство систем используют какую-либо блокирующую блокировку для обеспечения этой гарантии.

...