Верно ли, что уровень SERIALIZABLE устраняет взаимные блокировки?
Нет. SERIALIZABLE предотвращает некорректные конкурентные результаты, которые нельзя представить как последовательное выполнение, но взаимные блокировки могут сохраняться. Если транзакции удерживают несовместимые блокировки и ждут ресурсы друг друга, СУБД должна обнаружить цикл, прервать одну транзакцию или применить тайм-аут.
Идея сериализуемости появилась как способ сохранить корректность данных при параллельном выполнении: итог должен быть эквивалентен некоторому последовательному порядку транзакций. Это позволяет использовать конкурентность без отказа от предсказуемой логики последовательных операций.
Однако сериализуемость отвечает на вопрос о корректности результата, а не на вопрос о возможности ожидания. Блокировки применяются для защиты данных, и конфликтующие блокировки могут образовать цикл ожидания независимо от выбранного уровня изоляции.
Рассмотрим две транзакции, которые изменяют одни и те же ресурсы, но в разном порядке. Первая удерживает ресурс A и ждёт ресурс B, а вторая удерживает B и ждёт A. Ни одна из них не может продолжить работу, хотя их выполнение может быть сериализуемым после выбора порядка.
Если СУБД просто оставит транзакции ждать, возникнет бесконечное ожидание. Если она прервёт одну из них, приложение должно корректно обработать ошибку и обычно повторить всю транзакцию.
SERIALIZABLE контролирует допустимость конкурентного расписания, но не отменяет механизм ожидания блокировок. В блокировочной реализации строгая двухфазная блокировка может удерживать ресурсы до фиксации; при противоположном порядке захвата возникает цикл ожидания, то есть взаимная блокировка.
СУБД обычно ведёт граф ожидания: вершины графа — транзакции, а ребро означает, что одна транзакция ждёт ресурс, удерживаемый другой. Цикл показывает взаимную блокировку. Для продолжения работы СУБД выбирает жертву, откатывает её и освобождает блокировки; критерий выбора зависит от реализации.
В многоверсионных реализациях, например при использовании SSI, конфликт может завершиться ошибкой сериализации без обычного цикла блокировок. Это другая причина прерывания транзакции, но практическое требование схоже: приложение должно быть готово повторить транзакцию.
Устранить риск взаимных блокировок полностью одним переходом на SERIALIZABLE нельзя. Его снижают единым порядком доступа к ресурсам, короткими транзакциями, минимизацией удержания блокировок и ограничением времени ожидания. Тайм-аут полезен как защитный механизм, но сам по себе не доказывает наличие цикла: транзакция может ждать один ресурс слишком долго и без взаимной блокировки.
Сервис переводов одновременно обрабатывает операции между счетами. Одна транзакция сначала блокирует счёт отправителя, затем счёт получателя, а другая — те же счета в обратном порядке. При SERIALIZABLE обе транзакции не должны сформировать некорректный итог, но одна из них может попасть в взаимную блокировку.
Вариант с увеличением тайм-аута не устраняет причину: он лишь дольше удерживает ресурсы и повышает задержку. Полагаться только на случайный порядок повторов тоже рискованно, поскольку конфликт будет регулярно воспроизводиться.
Практичное решение — всегда упорядочивать счета по стабильному ключу, например сначала блокировать счёт с меньшим идентификатором, затем с большим. Дополнительно применяют ограничение времени ожидания и повтор всей транзакции после обнаружения взаимной блокировки или ошибки сериализации. Такой подход уменьшает число конфликтов, а повтор обеспечивает завершение временно прерванной операции.
Нет. Отсутствие циклов ожидания показывает только, что транзакции не застряли в данной системе блокировок. Некорректное расписание может не содержать взаимной блокировки, но всё равно нарушать сериализуемость, например из-за конфликтующих чтений и записей. Сериализуемость требует анализа зависимостей операций, а не только анализа ожиданий.
Потому что ошибка сериализации или взаимная блокировка означает, что наблюдения и решения внутри транзакции больше нельзя считать частью успешно завершённого последовательного сценария. Повтор только последнего оператора может использовать устаревшие промежуточные значения и нарушить логику бизнес-операции. Повторять нужно всю атомарную единицу, предварительно убедившись, что операция допускает безопасный повтор.
Нет. Он устраняет распространённый класс циклов, возникающих при доступе к одним ресурсам в противоположном порядке, но не покрывает все ресурсы и все типы блокировок. Дополнительные блокировки могут появляться из-за внешних ключей, индексов, триггеров, эскалации блокировок или обращения к другим таблицам. Поэтому порядок доступа должен быть согласован для всей затрагиваемой транзакцией совокупности ресурсов, а обработка ошибок взаимной блокировки всё равно необходима.