Почему не всегда стоит использовать самый высокий уровень изоляции транзакций
Что проверяют
Понимаете ли вы, что уровень изоляции это размен между аномалиями и пропускной способностью, и знаете ли реальное поведение своей СУБД, а не таблицу из учебника. Уточняют обычно, как приложение должно вести себя при ошибке сериализации.
Как отвечать
Начните с того, от чего защищает уровень: грязное чтение, неповторяемое чтение, фантомы, потерянное обновление и перекос записи (write skew). Стандарт описывает четыре уровня, но конкретика у каждой базы своя.
- PostgreSQL: по умолчанию
READ COMMITTED, аREAD UNCOMMITTEDфактически равен ему, грязного чтения нет вовсе.REPEATABLE READдаёт один снимок на всю транзакцию.SERIALIZABLEсделан как SSI: не блокировки, а отслеживание опасных пересечений, и при конфликте транзакция откатывается с ошибкой40001; - MySQL InnoDB: по умолчанию
REPEATABLE READ, фантомы прикрыты gap-блокировками, из-за которых легко словить взаимоблокировку на независимых с виду вставках.
Отсюда цена высокого уровня: не «медленно вообще», а рост числа откатов под конкуренцией плюс память на предикатные блокировки. На горячей строке SERIALIZABLE превращает нагрузку в очередь ретраев, и пропускная способность падает нелинейно.
Главное следствие: SERIALIZABLE требует поддержки в коде. В Go это sql.TxOptions{Isolation: sql.LevelSerializable} плюс обёртка, которая ловит коды 40001 и 40P01 и повторяет транзакцию заново. Значит она обязана быть короткой и повторяемой, а побочные эффекты (письмо, списание, сообщение в брокер) выносятся за её границы.
Закончите выбором по задаче: отчётам подходит REPEATABLE READ, обычному CRUD хватает READ COMMITTED, а точечную гонку дешевле закрыть SELECT ... FOR UPDATE или уникальным индексом.
Где спотыкаются
Пересказывают таблицу аномалий из учебника, не зная, что в их базе половина строк выглядит иначе.
Считают, что SERIALIZABLE в PostgreSQL блокирует читателей. Он их не блокирует, он откатывает проигравшую транзакцию, и без ретраев это выглядит как случайные ошибки.
Поднимают уровень и успокаиваются, не проверив длину транзакций. Долгая транзакция держит снимок, отодвигает горизонт xmin и мешает автоочистке, а это деградация всей базы.