Уровень изоляции транзакций Read Committed
Продолжим разбирать главу про транзакции из «кабанчика»? Ссылки на предыдущие главы есть в закрепе.
Транзакции, не затрагивающие одни и те же данные, могут выполняться конкурентно. Проблемы возникают, если одна транзакция читает данные, модифицируемые в этот момент другой, или две транзакции пытаются одновременно изменить одни и те же данные.
Базы данных долгое время пытались инкапсулировать вопросы конкурентного доступа от разработчиков приложений путем изоляции транзакций. Теоретически изоляция должна была облегчить жизнь разработчиков, которые смогли бы сделать вид, что никакого конкурентного выполнения нет: сериализуемая изоляция означает гарантию такого режима выполнения транзакций, как будто они выполняются последовательно 👨💻
На практике, к сожалению, с изоляцией не все так просто. Затраты на сериализуемую изоляцию высоки, поэтому многие системы часто задействуют более слабые уровни изоляции, защищающие от части проблем конкурентного доступа, а не от всех.
Read Committed (чтение зафиксированных данных) — это базовый уровень изоляции транзакций, включен по-умолчанию во многих БД.
Он обеспечивает две гарантии:
✅ При чтении из БД клиент видит только зафиксированные данные (никакого «грязного» чтения).
✅ При записи в БД можно перезаписывать только зафиксированные данные (никакой «грязной» записи).
📌«Грязное» чтение (dirty read) — это ситуация, при которой одна транзакция записала какие-то данные, но еще не зафиксировала их, а вторая транзакция прочитала эти не зафиксированные данные.
Почему это плохо?
➖ незафиксированные изменения могут быть откачены, а их уже прочитали
➖ можно принять неправильные решения, если первая транзакция содержала несколько записей, а вторая прочитала рано, когда обновилась только первая запись
Уровень read commited защищает от «грязных» чтений. Любые операции записи, выполняемые одной транзакцией, становятся видны другим транзакциям только после фиксации первой.
📌«Грязная» запись (dirty write) — это ситуация, при которой одна транзакция записала какое-то значение, но еще не зафиксировала это, а вторая транзакция перезаписала это незафиксированное значение.
Почему это плохо?
➖ конфликтующие записи могут оказаться перепутаны (пример на картинке к посту)
Уровень read commited защищает от «грязных» записей. Обычно это осуществляется путем откладывания второй операции записи, пока транзакция первой операции будет зафиксирована или прервана.
Некоторые БД поддерживают еще более слабый уровень изоляции — read uncommitted (чтение незафиксированных данных). Он предотвращает «грязную» запись, но не «грязное» чтение.
Для предотвращения «грязных» записей БД обычно используют блокировки строк: прежде чем модифицировать строку, транзакция должна сначала установить блокировку на нее и удерживать ее до фиксации или прерывания. Удерживать блокировку на конкретную строку может только одна транзакция одновременно. Другой транзакции, желающей выполнить операцию записи в эту строку, придется дождаться фиксации или прерывания первой транзакции и лишь затем получить блокировку и продолжить свою работу.
Для предотвращения «грязного» чтения теоретически можно воспользоваться теми же блокировками и потребовать, чтобы транзакции, желающие прочитать строку, устанавливали блокировку, освобождая ее сразу после чтения. Однако на практике требование блокировок чтения плохо сказывается на времени отклика — из-за случаев, когда множеству выполняющих только чтение транзакций приходится ждать завершения одной длительной транзакции записи.
Поэтому большинство БД предотвращают «грязные» операции чтения с помощью
другого подхода: база запоминает для каждого записываемого объекта как старое зафиксированное значение, так и новое, устанавливаемое транзакцией, удерживающей в данный момент блокировку записи. Во время выполнения транзакции всем другим транзакциям, читающим объект, просто возвращается старое значение.
Только после фиксации нового значения транзакции начинают получать его при чтении.
#кабанчик@jane_yanchenko #сисдиз@jane_yanchenko
Post #87
1.58K


- ❤ 12
- 👍 9
- 🔥 7