Приходилось ли менять уровни изоляции транзакций?
Что проверяют
Знаете ли вы, от каких аномалий защищает каждый уровень, и понимаете ли, что повышение уровня не бесплатно: в PostgreSQL оно не выстраивает очередь, а отменяет транзакции, и приложение обязано их повторять.
Как отвечать
Сначала аномалии: грязное чтение, неповторяющееся чтение, фантомы, аномалия сериализации. Дальше конкретика по своей базе, а не по учебнику. В PostgreSQL грязного чтения нет вовсе, READ UNCOMMITTED ведёт себя как READ COMMITTED, и это же уровень по умолчанию. REPEATABLE READ даёт снимок на всю транзакцию, фантомов не будет, но при конкурентной правке придёт ошибка сериализации с кодом 40001. SERIALIZABLE добавляет проверку на аномалии и тоже отдаёт 40001. В MySQL с InnoDB по умолчанию REPEATABLE READ, а фантомы подавляются блокировками промежутков.
В Go уровень задаётся на транзакцию:
tx, err := db.BeginTx(ctx, &sql.TxOptions{
Isolation: sql.LevelRepeatableRead,
})Обязательно скажите про повтор: транзакция целиком заворачивается в цикл с несколькими попытками и паузой, потому что после 40001 продолжать в ней уже нельзя.
Хороший финал ответа: часто уровень трогать не нужно. Атомарный UPDATE ... SET n = n + 1, SELECT ... FOR UPDATE или уникальный индекс решают задачу дешевле.
Где спотыкаются
Повторяют не транзакцию, а упавший запрос. Соединение уже в состоянии прерванной транзакции, и каждый следующий запрос падает с той же ошибкой, пока не пройдёт откат.
Думают, что SERIALIZABLE просто выстроит всех в очередь. В PostgreSQL он не ждёт, а отменяет одну из транзакций, и без обработки этой ошибки пользователь получает отказ на ровном месте.
Переносят ожидания от одной базы на другую. Уровни по умолчанию у PostgreSQL и MySQL разные, и рассказ про грязные чтения, которые случались в PostgreSQL, звучит как теория, ни разу не встречавшаяся с практикой.