Грязное чтение
Грязное чтение (англ. dirty read) — в информатике и теории баз данных ситуация, при которой транзакция считывает данные, записанные другой, ещё не завершённой (не зафиксированной) транзакцией. Данное явление относится к классу проблем параллельного доступа к данным и является одной из аномалий согласованности, возникающих при одновременной работе нескольких транзакций. Грязное чтение считается недопустимым в системах, требующих строгой изоляции транзакций, так как может привести к нарушению целостности данных, если незавершённая транзакция будет впоследствии отменена (откат).
Причины возникновения
Основной причиной грязного чтения является отсутствие или недостаточный уровень изоляции транзакций. В многопользовательских системах управления базами данных (СУБД) несколько транзакций могут выполняться одновременно, разделяя доступ к одним и тем же данным. Если одна транзакция (Транзакция A) изменяет запись, но ещё не зафиксировала изменения (не выполнила COMMIT), а другая транзакция (Транзакция B) считывает эту запись до завершения Транзакции A, то Транзакция B получает «грязные» данные. Если Транзакция A впоследствии будет отменена (выполнит ROLLBACK), данные, прочитанные Транзакцией B, окажутся недействительными, что может привести к логическим ошибкам в приложении или базе данных.
Грязное чтение возникает на самом низком уровне изоляции транзакций — Read Uncommitted (чтение незафиксированных данных). На этом уровне СУБД не блокирует записи, изменяемые другими транзакциями, и позволяет читать любые данные, независимо от их статуса.
Уровни изоляции транзакций
Для предотвращения грязного чтения и других аномалий параллельного доступа (неповторяющееся чтение, фантомное чтение) в стандарте SQL определена модель изоляции транзакций. Стандарт ANSI/ISO SQL-92 выделяет четыре уровня изоляции, различающихся по строгости:
- Read Uncommitted (чтение незафиксированных данных) — самый низкий уровень. Транзакция может читать данные, изменённые другими незавершёнными транзакциями. Допускает грязное чтение.
- Read Committed (чтение зафиксированных данных) — гарантирует, что транзакция читает только те данные, которые были зафиксированы другими транзакциями. Грязное чтение исключено, но возможны неповторяющееся чтение и фантомы.
- Repeatable Read (повторяемое чтение) — гарантирует, что данные, прочитанные в рамках одной транзакции, не изменятся другими транзакциями до её завершения. Исключает грязное чтение и неповторяющееся чтение, но допускает фантомное чтение.
- Serializable (сериализуемый) — самый высокий уровень. Транзакции выполняются так, как если бы они запускались последовательно, одна за другой. Полностью исключает все три аномалии, включая грязное чтение.
В большинстве современных СУБД (например, PostgreSQL, Oracle, Microsoft SQL Server) уровень изоляции по умолчанию установлен на Read Committed, что гарантирует отсутствие грязного чтения. Однако некоторые СУБД (например, MySQL с движком InnoDB) также используют Read Committed по умолчанию, но могут быть настроены на более низкий уровень.
Пример сценария
Рассмотрим типичный пример грязного чтения в банковской системе:
- Транзакция A начинает перевод средств со счёта 1 на счёт 2. Она уменьшает баланс счёта 1 на 1000 рублей, но ещё не завершила операцию (не выполнила COMMIT).
- Транзакция B, работающая на уровне Read Uncommitted, считывает текущий баланс счёта 1, который уже уменьшен на 1000 рублей, но изменения ещё не зафиксированы.
- Транзакция A по какой-либо причине отменяется (ROLLBACK), и баланс счёта 1 возвращается к исходному значению.
- Транзакция B, основываясь на «грязных» данных, продолжает свою работу, полагая, что на счёте 1 осталось меньше средств, чем на самом деле. Это может привести к неправильному расчёту комиссий, лимитов или к ошибочному списанию средств.
Методы предотвращения
Для предотвращения грязного чтения используются следующие механизмы:
- Блокировки (Locking) — СУБД накладывает блокировки на изменяемые строки или таблицы, запрещая другим транзакциям читать их до завершения текущей транзакции. Наиболее распространённый метод на уровне Read Committed и выше.
- Многоверсионность (MVCC, Multi-Version Concurrency Control) — СУБД создаёт несколько версий одной строки данных. Каждая транзакция видит «снимок» данных на момент её начала (или на момент последнего COMMIT), что исключает чтение незафиксированных изменений. MVCC используется в PostgreSQL, Oracle, MySQL (InnoDB) и позволяет избежать грязного чтения без использования блокировок на чтение.
- Установка уровня изоляции — при разработке приложения явно задаётся уровень изоляции транзакций, исключающий грязное чтение (обычно Read Committed или выше).
Применение и ограничения
Грязное чтение может быть допустимо в некоторых специализированных системах, где скорость доступа к данным критичнее, чем их абсолютная точность. Например, в аналитических системах реального времени, где данные постоянно обновляются, а небольшие расхождения в значениях не влияют на итоговый результат. Однако в большинстве промышленных систем (финансовые, банковские, CRM, ERP) грязное чтение недопустимо и должно быть исключено.
В системах, использующих репликацию данных, грязное чтение может возникать на ведомых (slave) узлах, если они отстают от ведущего (master) узла. В таких случаях применяются специальные механизмы синхронизации, гарантирующие, что данные, прочитанные с реплики, были зафиксированы на мастере.
См. также
- Неповторяющееся чтение
- Фантомное чтение
- ACID (кислотные свойства транзакций)
- Уровень изоляции транзакций
- Многоверсионность (MVCC)
Источники
- ISO/IEC 9075:1992, Information technology — Database languages — SQL. Международный стандарт, определяющий уровни изоляции транзакций.
- C. J. Date. An Introduction to Database Systems (8th Edition). Addison-Wesley, 2003. — Классический учебник по теории баз данных.
- Hector Garcia-Molina, Jeffrey D. Ullman, Jennifer Widom. Database Systems: The Complete Book (2nd Edition). Pearson, 2008. — Подробное описание параллельного доступа и аномалий.
- Документация PostgreSQL. Глава 13. Параллелизм и управление версиями данных. — Описание реализации MVCC и уровней изоляции в PostgreSQL.
- Документация MySQL. InnoDB Locking and Transaction Model. — Описание механизмов блокировок и изоляции в MySQL.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →