Рубрики
Без рубрики

Руководство для начинающих по аномалии чтения фантомов

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

Автор оригинала: Vlad Mihalcea.

Транзакции базы данных определяются четырьмя свойствами, известными как ACID . Уровень изоляции (I в ACID) позволяет вам обменять целостность данных на производительность.

Чем слабее уровень изоляции, тем больше аномалий может произойти, и в этой статье мы собираемся описать феномен фантомного чтения.

Руководство для начинающих по аномалии чтения фантомов – @vlad_mihalcea https://t.co/TJ6otpwu4V pic.twitter.com/dI9hPZ7gXK

Если транзакция принимает бизнес-решение на основе набора строк, удовлетворяющих заданному предикату, без блокировок диапазона, параллельная транзакция может вставить запись, соответствующую этому конкретному предикату.

На приведенной выше диаграмме поток утверждений выглядит следующим образом:

  1. Алиса и Боб запускают две транзакции с базой данных.
  2. Боб считывает все записи post_comment , связанные со строкой post со значением идентификатора 1.
  3. Алиса добавляет новую запись post_comment , которая связана со строкой post , имеющей значение идентификатора 1.
  4. Алиса совершает транзакцию с базой данных.
  5. Если Боб перечитает записи post_comment , имеющие значение столбца post_id , равное 1, он увидит другую версию этого результирующего набора.

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

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

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

Сериализуемая изоляция на основе 2PL предотвращает фантомное чтение с помощью блокировки предикатов, в то время как механизмы баз данных MVCC (Управление параллелизмом нескольких версий) устраняют аномалию фантомного чтения, возвращая согласованные моментальные снимки.

Однако параллельная транзакция все равно может изменить диапазон записей, которые были прочитаны ранее. Даже если компонент MVCC database engine проанализирует расписание транзакций, результат не всегда будет таким же, как при реализации на основе 2PL. Одним из таких примеров является случай, когда вторая транзакция выдает вставку, не считывая тот же диапазон записей, что и первая транзакция. В данном конкретном случае некоторые механизмы баз данных MVCC не завершат откат первой транзакции .

Это явление характерно как для незафиксированного чтения, так и для фиксированного чтения и для повторяемых уровней изоляции чтения. Уровень изоляции по умолчанию, являющийся либо Фиксированным для чтения (Oracle, SQL Server или PostgreSQL), либо повторяемым для чтения (MySQL), не предотвращает эту аномалию.

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