READ UNCOMMITTED позволяет читать грязные данные, которые не были зафиксированы другими транзакциями. Механизм SQL Server игнорирует любые блокировки под читаемой таблицей и считывает данные непосредственно из памяти.
READ COMMITTED прочитает данные, которые уже были COMMITTED, но будет ждать, если на данные повлияет другая транзакция.
Таким образом, в примере при условии, что система не только читает, но и пытается УДАЛИТЬ строку, которая еще не была ЗАВЕРШЕНА, поэтому оба будут ждать окончания другой транзакции, поэтому этот пример является типичным примером для DEADLOCK.
Чтобы проиллюстрировать различия между COMMITTED и UNCOMMITTED, я покажу вам простой и понятный пример, что мы будем работать дважды, в двух режимах.
-- Query Window 1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- Prepare for first Run
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- Prepare for second Run
BEGIN TRANSACTION -- Step 1
INSERT INTO Audit (ProductID, PrevValue, NewValue, ChangedBy)
VALUES (1, 'AAA', 'aaa', SYSTEM_USER); -- Step 3
COMMIT TRANSACTION -- Step 5
-- Query Window 2
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- Prepare for first Run
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- Prepare for second Run
BEGIN TRANSACTION -- Step 2
SELECT * FROM Audit WHERE PrevValue = 'AAA' -- Step 4
COMMIT TRANSACTION -- Step 6
Мы должны сначала запустить строку для НЕКОММИТИРОВАННОГО УРОВНЯ в обоих запросах, а затем перейти к первому, выполнить Шаг 1, перейти ко второму, Шаг 2 и так далее.
В UNCOMMITTED, когда мы запустим Шаг 4, мы сразу увидим результаты, так как мы делаем грязное чтение (из памяти).
Для второго запуска мы сначала удалим тест строки:
DELETE FROM Audit WHERE PrevValue LIKE 'AAA';
Затем запустит строку для COMMITTED LEVEL в обоих окнах запросов и выполнит ту же последовательность.
Мы увидим, что теперь, когда мы запускаем Шаг 4, система остается без ответа. В тот момент, когда мы запускаем шаг 5, чтобы зафиксировать вставку, окно покажет результаты.
Надеюсь, теперь вопрос яснее.