#sql-server #sql-server-2005 #transactions #isolation-level
#sql-server #sql-server-2005 #транзакции #уровень изоляции
Вопрос:
У меня есть оператор SQL, который выполняет обновление, а затем, если значение @@ROWCOUNT
равно 0, оно будет вставлено. это в основном a MERGE
в SQL 2008. Мы сталкиваемся с ситуациями, когда два потока не выполняют обновление одновременно. Он попытается дважды вставить один и тот же ключ в таблицу. Мы используем уровень изоляции транзакций по умолчанию, чтение зафиксировано. Исправит ли это изменение уровня на повторяемые чтения или мне нужно пройти весь путь до сериализации, чтобы заставить это работать? Вот некоторый код:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRAN;
UPDATE TableA
SET Duration = @duration
WHERE keyA = @ID
AND keyB = @IDB;
IF @@rowcount = 0
BEGIN
INSERT INTO TableA (keyA,keyB,Duration)
VALUES (@ID,@IDB,@duration);
END
COMMIT TRAN;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;";
Комментарии:
1. Вы не получаете грязных чтений с уровнем изоляции транзакции, зафиксированной для чтения. Вы можете получать грязные чтения только с незафиксированным чтением.
2. Извините, хотел сказать — сделать обновление и вставку атомарными. Как мне их объединить
Ответ №1:
Вам нужно будет пройти весь путь до SERIALIZABLE
.
REPEATABLE READ
Если строка не существует, то оба UPDATE
оператора могут выполняться одновременно, не блокируя друг друга, и переходить к выполнению вставки. В SERIALIZABLE
диапазоне, где должна была находиться строка, заблокирована.
Но вам также следует рассмотреть возможность оставить уровень изоляции по умолчанию read committed
и установить ограничение уникальности keyA,keyB
, чтобы любые попытки вставить дубликат завершались ошибкой.