Вопрос транзакции новичка sql: предотвращение гонки в чтении - вычислить-записать - PullRequest
5 голосов
/ 14 сентября 2011

Я хочу сделать следующее в одной транзакции:

  • читать столбец
  • если значение столбца соответствует определенному условию, записать новое значение в столбец

изоляция транзакции установлена ​​на чтение, сервер является сервером SQL.

Как я могу гарантировать, что другая транзакция не записывает другое значение в столбец после того как я прочитал это? Будет ли сервер отклонять мою запись, если другая транзакция изменила столбец?

Другими словами, можно ли использовать сервер SQL в качестве распределенной блокировки для данного столбца?

Ответы [ 2 ]

4 голосов
/ 14 сентября 2011

Кто сказал, что вы должны сначала прочитать его?

UPDATE yourtable
SET    yourcolumn = CASE
                      WHEN certaincondition = 1 THEN 'newvalue'
                      ELSE yourcolumn
                    END
WHERE  id = 'yourid'  

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

1 голос
/ 14 сентября 2011

В этом случае вам необходимо использовать REPEATABLE READ уровень изоляции. С READ COMMITTED другая транзакция может изменить вашу запись.
Если вы можете переписать свою логику в 1 запросе (например, с помощью update или merge), вы все равно можете использовать READ COMMITTED. Но иногда это не вариант. Например,

SELECT ... ;
IF some_condition
BEGIN
  // execute a procedure, select from other tables, etc
END
ELSE
BEGIN
  // execute another procedure, do some other stuff
END;
// finally update the record
UPDATE ....

Обновление

Есть еще одна опция, о которой я забыл упомянуть: используйте табличную подсказку REPEATABLEREAD в своем SELECT выражении ( Подробнее см. )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...