Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add transaction_isolations.md #314

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Nikita777-coder
Copy link
Contributor

@Nikita777-coder Nikita777-coder commented Feb 4, 2025

Название

Транзакции и обеспечение безопасности и параллельности в них

Введение

Транзакции - действия (CRUD), которые происходят при обращении в бд в одном методе/клиенте и т. д. Группа операций в БД

В ходе совершения операций транзакции возникают такие вопросы

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

Основная часть

Для решения данных были сформированы 4 принципа ACID:

ACID или 4 свойства транзакций

  • Atomicity (атомарность) — св-во выполнения всех операций в транзакции с её дальнейшим комитом базу/гарантирует, что никакая транзакция не будет зафиксирована в базе частично. То есть она должна быть выполнена вся с дальнейшими комитом или вовсе не выполнится с дальнейшим откатом (rollback)
  • Consistency (согласованность) — гарантия, что данные в конце транзакции будут зафиксированы с тем порядком, который предполагался до транзакции. Например, выполняется перевод с одного счета на другой. Ожидается, что по окончании транзакции вычтется сумма у человека, который переводил, и передастся та сумма человеку, которому он переводил. Не больше, не меньше. Не должно быть дополнительных вычетов или снятия/перечисления средств только одному из людей
  • Isolation (изолированность) — про то, что несмотря на несколько транзакциий результат в БД должен быть одним и тем же. То есть не должно быть такого, что несколько операций одной транзакции смешались с другой. Или не должно быть такого, чтобы стали видны незакомиченные данные (если видны незакомиченные данные, то это назывется грязное чтение (уровень изоляции read_uncommited)) другой транзакции. Другими словами другие транзакции не должны оказывать влияние на текущую транзакцию
  • Durability (устойчивость) — устойчивость к ошибкам — если транзакция завершена успешно, то те изменения в данных, которые были ею произведены, не могут быть потеряны ни при каких обстоятельствах.

Рассмотрим же, какие были придуманы вещи для удовлетворения условиям выше:

Изоляция

Всего существует 4 вида изоляции:

  • SERIALIZABLE
  • REPEATABLE_READ
  • READ_COMMITTED
  • READ_UNCOMMITTED

1. SERIALIZABLE

При данном уровне изоляции каждая транзакция изолирована от другой. То есть изменения видны только локально (только в одной транзакции). При этом она позволяет совершать обновление одной и той же записи только один раз при параллельных транзакциях, что обеспечивает согласованность данных. Однако при получении таблицы с обновленной информацией и закомиченной транзакцией в параллельно запущенных с первой транзакциях будет видна старая версия таблицы для обеспечения безопасности. И, если попытаться вставить уже существующую запись, которую не видно в данной транзакции, то мы получим ошибку и все модифицирующие действия при комите транзакции будут отменены (rollback, откат произойдёт). Но при этом в транзакции, запущенной после коммита транзакции, зафиксировавшей изменения в таблице мы увидим уже обновленную таблицу. Для более подробного объяснения, понимания смотреть 1-ую ссылку из "Ссылки на используемые в статье материалы"

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

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

"+" данного уровня в том, что он обеспечит строгую и безопасную согласованности данных

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

2. READ_COMMITTED

В ReadCommited не накладывается блокировка на модифицирующую операцию параллельной транзакции, если одна из транзакций закоммитилась + будут видны все закомиченные изменения из незакомиченной тарнзакции. То есть при данном уровне изоляции можно бесконечно модифицировать один и тот же элемент из бд.

Пример:

Первая транзакция собирается уменьшить сумму на счете на 100 ₽. Она проверяет текущее значение, получает 1000 ₽ и решает, что уменьшение возможно. В это время вторая транзакция параллельно уменьшает сумму на счете до нуля и фиксирует изменения. Если бы теперь первая транзакция повторно проверила сумму, она получила бы 0 ₽ (но она уже приняла решение уменьшить значение, и счет “уходит в минус”).

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

3. REPEATABLE_READ

Данный уровень изоляции транзакции похож на SERIALIZABLE так, как фиксирует состояние базы, с которой она и начала, и все изменения фиксируует лишь внутри транзакции, не распространяя их на другие параллельные транзакции. В select запросе будут видны только данные, зафиксированные на момент начала транзакции. Команды UPDATE, DELETE, SELECT FOR UPDATE и SELECT FOR SHARE ведут себя подобно SELECT при поиске целевых строк: они найдут только те целевые строки, которые были зафиксированы на момент начала транзакции. Однако к моменту, когда они будут найдены, эти целевые строки могут быть уже изменены (а также удалены или заблокированы) другой параллельной транзакцией. В этом случае транзакция в режиме Repeatable Read будет ожидать фиксирования или отката первой изменяющей данные транзакции (если она ещё выполняется). Если первая изменяющая транзакция откатывается, её результат отбрасывается и текущая транзакция может продолжить изменение изначально полученной строки. Если же первая транзакция зафиксировалась и в результате изменила или удалила эту строку, а не просто заблокировала её, произойдёт откат текущей транзакции

Фантомное чтение vs неповторяющееся чтение

В неповторяющемся чтении задейстованы модификации только одной строки/задействована только одна строка.
В то время как в фантомном чтении несколько и там не видны изменения над строкой/строками.

Пример, показывающий разницу между :

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

Заключение

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

Полезные ссылки

  1. Уровни изоляции транзакций в PostgreSQL
  2. Уровни изоляции транзакций
  3. Уровни изоляции транзакций 2

Отдельная благодарность

Nikita777-coder

@aarexer
Copy link
Collaborator

aarexer commented Feb 7, 2025

Спасибо за статью!

Я предлагаю это оформить как вопрос с собеседования и вынести в interview/questions/medium/transaction_isolations.md

Так как с точки зрения развернутой статьи тут не совсем полно и обширно (в сравнении даже с хабр ссылками), а вот как ответ на собеседовании подойдет хорошо!

Как оформлять задачи с интервью: https://github.com/qcha/JBook/blob/master/design_requirements.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants