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

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

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

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

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

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

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

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

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

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

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

Если в базе данных используется 2PL (Двухфазная блокировка) и при каждом чтении выполняются общие блокировки, это явление будет предотвращено, поскольку ни одной параллельной транзакции не будет разрешено получить эксклюзивную блокировку для одной и той же записи базы данных.

Большинство систем баз данных перешли на модель MVCC (управление параллелизмом с несколькими версиями), и общие блокировки больше не являются обязательными для предотвращения неповторяемых операций чтения.

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

Повторяемое чтение и сериализуемость по умолчанию предотвращают эту аномалию. С фиксацией чтения можно избежать неповторяемых (нечетких) считываний, если общие блокировки получены явно (например, ВЫБЕРИТЕ ДЛЯ ОБЩЕГО ДОСТУПА ).

Некоторые платформы ORM (например, JPA/Hibernate) предлагают повторяемые чтения на уровне приложений. Первый снимок любого извлеченного объекта кэшируется в текущем контексте Сохраняемости .

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

Это явление характерно как для уровней изоляции с незафиксированным чтением, так и для уровней изоляции с фиксированным чтением. Проблема в том, что Read Committed является уровнем изоляции по умолчанию для многих СУБД, таких как Oracle, SQL Server или PostgreSQL, поэтому это явление может произойти, если ничего не сделать для его предотвращения.

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