2.5Kпросмотров
22 ноября 2025 г.
Score: 2.8K
🧡🔹🔸💮 Как уровни изоляции транзакций в БД влияют на безопасность операций Один из кейсов, который когда-то мне предлагали решить на собеседованиях звучал следующим образом: У человека на банковском счете находится 1000 рублей. Человек очень хитрый, и пытается обмануть банковскую систему, одновременно сняв 1000 рублей со счета карты через банкомат, и в этот же момент перевести 1000 рублей через мобильное приложение на свой счет в другой банк.
Предположим, что ему удалось идеально одновременно инициировать две операции.
Как защититься от двойного списания денег? Можно много и долго рассуждать на эту тему с точки зрения архитектуры, но довольно простое и элегантное решение заключается в выборе нужного уровня изоляции транзакций в БД. Каждый уровень изоляции транзакций допускает определённые аномалии и по-разному защищает БД от аномалий в данных, а в случае нашего кейса - от дублирующего списания денег. 1⃣ Read Uncommitted (Чтение незафиксированных данных) — самый ненадёжный уровень.
Что происходит: Одна операция (например, снятие) может видеть данные, которые всё ещё не подтверждены в другой операции (перевод).
Риск: Может пройти двойное списание — обе операции «увидят» баланс 1000₽ и будут исполнены.
Вывод: Не используется в доменах, критичных к риску «грязного» чтения, особенно, если речь касается финансов. 2⃣ Read Committed (Чтение подтверждённых данных) - уровень по умолчанию для PostgreSQL.
Что происходит: Каждая операция читает только значения, подтверждённые в других транзакциях. Но между отдельными действиями внутри одной операции данные могут измениться.
Риск: Если обе транзакции стартуют почти одновременно, обе увидят баланс 1000₽ и смогут пройти проверки. Итог — обе операции могут быть закоммичены, и счет уйдёт в минус, если нет внешней проверки ограничений.
Вывод: Возможна ситуация «потери обновления». Требуются дополнительные ограничения на уровне БД (например, уникальные ограничения или блокировки). 3⃣ Repeatable Read (Повторяемое чтение)
Что происходит: Гарантируется, что если транзакция стартовала, баланс для неё не изменится до конца транзакции.
Риск: Исключаются «грязные» и «неповторяющиеся» чтения. Но может появляться аномалия «фантомов» — конкурирующая вставка или удаление строк.
Вывод: Вероятность двойного списания ниже, но все еще не исключена полностью. 4⃣ Serializable (Сериализуемый — максимальная изоляция)
Что происходит: Все параллельные транзакции выполняются так, как если бы они шли строго поочерёдно. На время исполнения транзакции блокируется та часть БД, с которой транзакция работает.
Риск: Исключены все типы аномалий — ни одна транзакция не начнется, до тех пор пока не выполнится предыдущая.
Вывод: Гарантировано отсутствие двойного списания, но возможны откаты транзакций и снижение пропускной способности из-за блокировки. 🔥 Хорошее обзорное видео с ютуба с примерами про транзакции в БД https://www.youtube.com/watch?v=s4_bROEL4vQ P.S. Если есть кто-то, то работал в процессинге, то поделитесь боевым опытом плиз, очень интересно как оно в жизни 🧐