Разница между чтением фиксации и повторяемым чтением

Я думаю, что вышеупомянутые уровни изоляции настолько похожи. Может ли кто-нибудь описать с некоторыми хорошими примерами, в чем основное отличие?

Ответ 1

Чтение завершено - это уровень изоляции, который гарантирует, что чтение данных было совершено в данный момент. Это просто ограничивает восприятие читателем какого-либо промежуточного, незафиксированного, "грязного" чтения. ИТ не дает никаких обещаний, что если транзакция переиздает чтение, она найдет те же данные, данные могут быть изменены после ее чтения.

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

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

Скажем, у вас есть таблица T со столбцом C с одной строкой в ней, скажем, что она имеет значение "1". И подумайте, что у вас есть простая задача:

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;

Это простая задача, которая выдает два чтения из таблицы T с задержкой в 1 минуту между ними.

  • при READ COMITTED второй SELECT может возвращать любые данные. Параллельная транзакция может обновить запись, удалить ее, вставить новые записи. Второй выбор всегда будет видеть новые данные.
  • в разделе REPEATABLE READ второй SELECT гарантированно увидит строки, которые сначала увидели без изменений. Новые строки могут быть добавлены посредством одновременной транзакции за одну минуту, но существующие строки не могут быть удалены или изменены.
  • при SERIALIZABLE читается, что второй select гарантированно будет видеть точно такие же строки, что и первый. Никакая строка не может быть изменена или удалена, а новые строки не могут быть вставлены параллельной транзакцией.

Если вы следуете логике выше, вы можете быстро понять, что SERIALIZABLE транзакции, в то время как они могут сделать жизнь легкой для вас, всегда полностью блокируют все возможные параллельные операции, поскольку они требуют, чтобы никто не мог изменять, удалять и вставлять какую-либо строку. Уровень изоляции транзакций по умолчанию для области.Net System.Transactions является сериализуемым, и это обычно объясняет невероятную производительность.

И, наконец, существует также уровень изоляции SNAPSHOT. Уровень изоляции SNAPSHOT обеспечивает те же гарантии, что и сериализуемый, но не требует, чтобы никакая параллельная транзакция не могла изменять данные. Вместо этого он заставляет каждого читателя видеть его собственную версию мира (собственный "моментальный снимок"). Это упрощает программирование, а также очень масштабируемое, поскольку оно не блокирует одновременные обновления. Однако это преимущество связано с ценой: дополнительным потреблением ресурсов сервера.

Дополнительное сообщение:

Ответ 2

Повторяемое чтение

Состояние базы данных сохраняется с начала транзакции. Если вы получите значение в session1, то обновите это значение в session2, получив его снова в session1, вернет те же результаты. Считывание повторяемо.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Aaron

Чтение завершено

В контексте транзакции вы всегда будете получать последнее зафиксированное значение. Если вы получите значение в session1, обновите его в session2, а затем извлеките его в session1again, вы получите значение, измененное в session2. Он читает последнюю зафиксированную строку.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Bob

Имеет смысл?

Ответ 3

Просто ответ в соответствии с моим чтением и пониманием этой темы, а ответ @remus-rusanu основан на этом простом сценарии:

Существует два процесса A и B. Процесс В считывает таблицу X Процесс А записывается в таблице X Процесс B снова читает таблицу X.

  • ReadUncommitted: процесс B может считывать незафиксированные данные из процесса A, и он может видеть разные строки на основе записи B. Нет блокировки вообще
  • ReadCommitted. Процесс B может читать ТОЛЬКО зафиксированные данные из процесса A, и он может видеть разные строки на основе COMMITTED только B записи. Можно ли назвать его простой блокировкой?
  • RepeatableRead. Процесс B будет считывать те же данные (строки), которые выполняются в процессе A. Но процесс A может изменить другие строки. Блок уровней строк
  • Сериализуемый. Процесс B будет читать те же строки, что и раньше, и Process A не может читать или писать в таблице. Блок уровня таблицы
  • Снимок: каждый процесс имеет свою собственную копию, и они работают над ней. Каждый имеет свой собственный вид

Ответ 4

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

READ COMMITTED (по умолчанию)

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

REPEATABLE READ

Общие блокировки берутся в SELECT, а затем освобождаются только после завершения транзакции. Таким образом система может гарантировать, что прочитанные вами значения не будут меняться во время транзакции (поскольку они остаются заблокированными до завершения транзакции).

Ответ 5

Попытка объяснить это сомнение простыми диаграммами.

Read Committed: Здесь, на этом уровне изоляции, Transaction T1 будет считывать обновленное значение X, совершенное транзакцией T2.

Read Committed

Повторяемое чтение: на этом уровне изоляции Transaction T1 не будет рассматривать изменения, совершенные транзакцией T2.

enter image description here

Ответ 6

Я думаю, что эта картинка также может быть полезна, она помогает мне в качестве ссылки, когда я хочу быстро запомнить различия между уровнями изоляции (благодаря кудвенкату на youtube)

enter image description here

Ответ 7

Обратите внимание, что повторяемое в повторяемом чтении относится к кортежу, но не ко всей таблице. На уровнях изоляции ANSC может возникнуть аномалия фантомного чтения, что означает, что чтение таблицы с одним и тем же предложением where дважды может возвращать разные возвращаемые разные наборы результатов. Буквально это не повторяется.

Ответ 8

Мое наблюдение за первоначальным принятым решением.

В RR (по умолчанию mysql). Если tx открыт и SELECT был запущен, другой tx НЕ может удалить любую строку, принадлежащую предыдущему набору результатов READ, пока не будет зафиксировано предыдущее tx (фактически оператор delete в новом tx будет просто повесить), однако следующий tx может без проблем удалить все строки из таблицы. Btw, следующий READ в предыдущем tx все равно будет видеть старые данные до тех пор, пока они не будут зафиксированы.