В чем разница между неповторяющимся чтением и фантомным чтением?

74

В чем разница между неповторяемым чтением и phantom read?

Я прочитал статью Изоляция (системы баз данных) из Википедии, но у меня есть несколько сомнений. В приведенном ниже примере произойдет следующее: не повторяемый читать и phantom читать?

Транзакция A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1
ВЫВОД:
1----MIKE------29019892---------5000
Транзакция B
UPDATE USERS SET amount=amount+5000 where ID=1 AND accountno=29019892;
COMMIT;
Транзакция A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1

Еще одно сомнение заключается в том, что в приведенном выше примере должен использоваться уровень изоляции? И почему?

Теги:
isolation-level
transaction-isolation

6 ответов

85
Лучший ответ

Из Википедии (в котором есть большие и подробные примеры для этого):

Непрерывное чтение происходит, когда во время транзакции строка извлекается дважды, а значения внутри строки отличаются друг от друга.

и

A phantom чтение происходит, когда в ходе транзакции выполняются два идентичных запроса, а набор строк, возвращаемых вторым запросом, отличается от первого.

Простые примеры:

  • Пользователь A дважды выполняет один и тот же запрос.
  • В промежутке между Пользователем B выполняется транзакция и выполняется.
  • Непрерывное чтение: строка, которую запросил пользователь A, имеет второй раз.
  • Phantom read: Все строки запроса имеют одно и то же значение до и после, но выбираются разные строки (поскольку B удалил или вставил некоторые). Пример: select sum(x) from table; возвращает другой результат, даже если ни одна из затронутых строк не была обновлена, если строки были добавлены или удалены.

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

Какой уровень изоляции вам нужен, зависит от вашего приложения. Существует высокая стоимость "лучшего" уровня изоляции (например, уменьшенная concurrency).

В вашем примере вы не будете читать phantom, потому что вы выбираете только одну строку (идентифицированную первичным ключом). Вы можете иметь не повторяющиеся чтения, поэтому, если это проблема, вы можете захотеть иметь уровень изоляции, который предотвращает это. В Oracle транзакция A также может выдавать SELECT FOR UPDATE, тогда транзакция B не может изменить строку до тех пор, пока не будет выполнена A.

  • 4
    Я не очень понимаю логику такого синтаксиса ... Неповторяемое чтение происходит, когда чтение повторяется (и получается другое значение) ??! ...
  • 6
    @serhio «неповторяемый» относится к тому факту, что вы можете прочитать значение один раз и получить x в качестве результата, а затем снова прочитать и получить y в качестве результата, так что вы не можете повторить (неповторяемые) одинаковые результаты из двух отдельные запросы одной и той же строки, потому что это значение строки было обновлено между чтениями.
Показать ещё 2 комментария
56

Простым способом, который мне нравится думать, является:

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

Непрерывные чтения - это когда ваша транзакция считывает заверенные ОБНОВЛЕНИЯ из другой транзакции. Такая же строка имеет разные значения, чем при начале транзакции.

Phantom чтения аналогичны, но при чтении из объявленных ВСТАВКИ и/или DELETES из другой транзакции. Появляются новые строки или строки, которые исчезли с момента начала транзакции.

Грязные чтения похожи на неповторяющиеся и phantom чтения, но относятся к чтению данных UNCOMMITTED и происходят при чтении UPDATE, INSERT или DELETE из другой транзакции, а другая транзакция еще не передала данные, Он считывает данные "в процессе", которые могут быть неполными и никогда не могут быть выполнены.

  • 0
    Я поражен (или говорю, что не верю). Грязное чтение: чтение измененных данных (другой транзакцией), которые на самом деле не зафиксированы или могут никогда не быть зафиксированы. Где, возможно, этот сценарий может быть использован? (Это не я вам не верю - На самом деле я не понял концепцию должным образом) - Пожалуйста, не возражайте (Возможно, вы сможете понять разочарование новичка)
  • 3
    Это связано с уровнями изоляции транзакций и параллелизмом. Используя уровень изоляции по умолчанию, вы не получите грязное чтение, и в большинстве случаев вы хотите избежать грязного чтения. Существуют уровни изоляции или подсказки запросов, которые допускают грязное чтение, что в некоторых случаях является приемлемым компромиссом для достижения более высокого уровня параллелизма или необходимо из-за пограничного случая, такого как устранение неполадок в текущей транзакции из другого соединения. Хорошо, что идея грязного чтения не проходит для вас «тест на запах», потому что, как правило, их следует избегать, но у них есть цель.
Показать ещё 11 комментариев
4

Существует разница в реализации между этими уровнями изоляции двух типов.
Для "неповторяющегося чтения" требуется блокировка строк.
Для "phantom read" требуется блокировка с привязкой, даже блокировка таблицы.
Мы можем реализовать эти два уровня, используя двухфазную блокировку.

  • 0
    Для реализации повторяемого чтения или сериализации нет необходимости использовать блокировку строк.
3

В системе с неповторяющимися чтениями результат второго запроса транзакции будет отражать обновление в транзакции B - он увидит новую сумму.

В системе, которая позволяет читать phantom, если Transaction B должен был вставить новую строку с ID = 1, Transaction A увидит новую строку при выполнении второго запроса; то есть phantom чтение является частным случаем не повторяемого чтения.

  • 0
    Я не думаю, что объяснение фантомного чтения правильное. Вы можете получить фантомное чтение, даже если данные без фиксации никогда не видны. Смотрите пример в Википедии (ссылка в комментариях выше).
1

Принятый ответ указывает прежде всего на то, что так называемое различие между ними фактически не имеет значения вообще.

Если "строка извлекается дважды, а значения внутри строки отличаются друг от друга", то они не являются одной и той же строкой (не такой же кортеж в правильной речи RDB), и тогда действительно по определению также случай, сбор строк, возвращаемых вторым запросом, отличается от первого ".

Что касается вопроса "какой уровень изоляции следует использовать", тем больше ваши данные имеют жизненно важное значение для кого-то, где-то, тем больше будет случай, когда Serializable является вашим единственным разумным вариантом.

0

Грязное чтение: прочитайте НЕОБХОДИМЫЕ данные из других транзакций.

Непрерывное чтение: прочитайте COMMITED данные из запроса UPDATE из другой транзакции.

Phantom читать: читать COMMITED данные из запроса INSERT или DELETE из другой транзакции.

Обратите внимание на то, что UPDATES может быть более частым занятием в некоторых случаях, а не в фактических INSERT или DELETES. В таких случаях остается опасность чтения не повторяющихся чтений - phantom в этих случаях чтение невозможно. Это почему UPDATES обрабатываются иначе, чем INSERT-DELETE, и соответствующая аномалия также называется по-разному.

Существует также дополнительная стоимость обработки, связанная с обработкой для INSERT-DELETES, а не просто обработка UPDATES.

Уровень изоляции TRANSACTION_READ_UNCOMMITTED не предотвращает ничего. Его уровень нулевой изоляции.

Уровень изоляции TRANSACTION_READ_COMMITTED предотвращает только одно, т.е. Грязный читает.

Уровень изоляции TRANSACTION_REPEATABLE_READ предотвращает две аномалии: Грязные чтения и Непрерывные чтения.

Уровень изоляции TRANSACTION_SERIALIZABLE предотвращает все три аномалии: Dirty reads, Non-repeatable reads и phantom читает.

Тогда почему бы просто не установить транзакцию SERIALIZABLE во все времена?

Ну, ответ на этот вопрос: SERIALIZABLE устанавливает очень медленные транзакции, которых мы опять не хотим.

Фактическое потребление времени транзакции имеет следующую скорость:

SERIALIZABLE > REPEATABLE_READ > READ_COMMITTED > READ_UNCOMMITTED.

Таким образом, настройка READ_UNCOMMITTED является самой быстрой.

На самом деле нам нужно проанализировать usecase и определить уровень изоляции, чтобы мы оптимизировали время транзакции, а также предотвратили большинство аномалий.

Обратите внимание, что базы данных по умолчанию имеют параметр REPEATABLE_READ.

  • 0
    ОБНОВЛЕНИЕ или УДАЛЕНИЕ оба могут иметь место для неповторяющихся чтений, или это только ОБНОВЛЕНИЕ?
  • 0
    ОБНОВЛЕНИЕ или УДАЛЕНИЕ оба могут иметь место для неповторяющихся чтений

Ещё вопросы

Сообщество Overcoder
Наверх
Меню