Read Committed vs Read Uncommited, если обе транзакции не отменены - PullRequest
0 голосов
/ 06 января 2019

Я пытаюсь понять, зафиксированы ли прочитанные и незафиксированные уровни изоляции. Я знаю, что теоретическое чтение без передачи допускает грязное чтение, а чтение с фиксацией - нет, но я все еще не могу понять.

this example

Учитывая рисунок выше, если ни одна из транзакций не была прервана, то конечный результат будет одинаковым как для зафиксированного чтения, так и для незафиксированного чтения?

Ответы [ 4 ]

0 голосов
/ 13 июля 2019

Пожалуйста, найдите ссылку https://www.postgresql.org/docs/9.5/transaction-iso.html

Я переписываю

13.2.1. Чтение подтвержденного уровня изоляции

Read Committed - уровень изоляции по умолчанию в PostgreSQL. Когда транзакция использует этот уровень изоляции, SELECT запрос (без FOR UPDATE/SHARE предложение) видит только данные, зафиксированные перед запросом началось; он никогда не видит ни незафиксированные данные, ни зафиксированные изменения во время выполнения запроса параллельными транзакциями. По сути, SELECT запрос видит моментальный снимок базы данных на момент запрос начинает выполняться. Тем не менее, SELECT видит эффект предыдущие обновления выполнялись в рамках собственной транзакции, даже если они еще не совершены. Также обратите внимание, что две последовательные команды SELECT можно увидеть разные данные, даже если они находятся в пределах одного транзакция, если другие транзакции фиксируют изменения после первой SELECT начинается и до начала второго SELECT.

UPDATE, DELETE, SELECT FOR UPDATE и SELECT FOR SHARE Команды ведут себя так же, как SELECT в плане поиска цели строки: они найдут только целевые строки, которые были зафиксированы с время начала команды. Однако такая целевая строка, возможно, уже была обновлен (или удален или заблокирован) другой параллельной транзакцией время это найдено. В этом случае будущий обновитель будет ждать первая обновляемая транзакция для фиксации или отката (если она все еще в ходе выполнения). Если первый апдейтер откатывается, то его эффекты отрицается, и второй обновитель может продолжить обновление изначально найденный ряд. Если первый обновитель фиксирует, второй обновитель фиксирует проигнорирует строку, если первый обновитель удалил ее, в противном случае она будет попытаться применить свою операцию к обновленной версии строки. условие поиска команды (предложение WHERE) переоценивается чтобы увидеть, соответствует ли обновленная версия строки поиску состояние. Если это так, второй модуль обновления продолжает свою работу, используя обновленная версия строки. В случае SELECT FOR UPDATE и SELECT FOR SHARE, это означает, что это обновленная версия строки который заблокирован и возвращен клиенту.

0 голосов
/ 06 января 2019

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, чтобы зафиксировать вставку, окно покажет результаты.

Надеюсь, теперь вопрос яснее.

0 голосов
/ 07 января 2019

Ваш пример не имеет ничего общего с Isolation Levels. Это потому, что они влияют на поведение readers, а не writers, и в вашем примере есть только writers.

Вы должны обратиться к этой статье BOL: Понимание уровней изоляции что говорит

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

В вашем примере нет ни одной транзакции read, они обе modify. Первая транзакция получит X для заинтересованных RID или key (зависит от структуры таблицы, если это куча или кластеризованная таблица) - я назову это res_1 в будущем - для вставка и будет удерживать ее на протяжении всей транзакции (она также будет иметь IX на соответствующих page и object), и то же самое относится и к первому оператору второй транзакции: она получит X res_2 при вставке.

При попытке DELETE вторая транзакция будет заблокирована, поскольку она не может получить X (или U в случае отсутствия индекса в условии where), это потому, что уже X включено тот же ресурс ( res_1 ) удерживается первой транзакцией. И не будет второго INSERT во второй транзакции, потому что предыдущий DELETE заблокирован.

Наконец, когда первая транзакция пытается выполнить DELETE, ей нужно X или U (в зависимости от существования индекса) на res_2, но она уже заблокирована с X с помощью tran2, поэтому она также заблокирована и выхода из этой ситуации нет, каждый сеанс ожидает завершения другого сеанса, и ни один сеанс не может быть завершен, в этот момент происходит deadlock, и сервер разрешает его с помощью rolling back одной из транзакций.

0 голосов
/ 06 января 2019

Если вы работаете с уровнем изоляции фиксации чтения, T2 нужно подождать на шаге 4, чтобы T1 завершил и зафиксировал свою работу. кроме того, T1 на шаге 6 не может найти Nome с Maria%, таким образом, удаляет 0 строк.

но на уровне изоляции незафиксированного чтения обе операции чтения / записи могут выполняться одновременно.

Результат Для уровня готовности к чтению,

Pessoas (Jaoa Silva, 96.....)
Pessoas (Maria Fon..., 9199...)
Pessoas (Joao Manuel Silva, 9699...)

тогда как для чтения незафиксированный уровень изоляции

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