Уровень изоляции транзакций Serializable
Сегодня заканчиваем главу кабанчика («Высоконагруженные приложения» Мартина Клепманна) про транзакции. Нам остался раздел про сериализуемость. Предыдущие разделы и главы в закрепе.
Сериализуемость — это самый строгий уровень изоляции. Он гарантирует, что даже при конкурентном выполнении транзакций результат будет таким же, как и в случае их последовательного выполнения.
Сериализуемость может достигаться следующим методами:
✅действительно последовательным выполнением транзакций
✅двухфазной блокировкой
✅сериализуемой изоляцией снимков состояния
В этой главе эти методы рассматриваются применительно к базе из одного узла.
Последовательное выполнение
Простейший способ избежать проблем с конкурентным доступом — отказаться от него: выполнять одновременно только одну транзакцию, последовательно, в одном потоке выполнения. Нет конкурентности — нет проблем.
Однако у такого подхода есть свои особенности:
🟡все транзакции должны быть маленькими и быстрыми, поскольку одна-единственная медленная транзакция может застопорить всю работу
🟡набор данных должен помещаться в памяти целиком
🟡количество транзакций на запись должно быть таким, чтобы они могли быть обработаны на одном ядре процессора
Например, in-memory хранилище Redis до 6-й версии однопоточный, и работает быстро. При большом количестве запросов он скорее упрется в пропускную способность сети, чем процессора.
Двухфазная блокировка (two phase locking)
Обратите внимание, это не двухфазный комит, просто похожее название.
При двухфазной блокировке если транзакция читает объект, а вторая хочет сделать запись этого объекта, то второй придется подождать, чтобы не изменить объект «за спиной» первой транзакции. Также если одна транзакция уже пишет в объект, то второй нельзя его читать, чтобы не прочитать старую версию.
На каждом объекте в БД имеется блокировка, которая может находиться или в разделяемом (shared mode), или в монопольном режиме (exclusive mode).
Для обеспечения сериализуемости транзакции используют эти блокировки. Сам подход называется «двухфазной блокировкой», потому что есть фаза получения блокировок и фаза их освобождения.
Из-за большого количества блокировок часто встречается ситуация взаимной блокировки (deadlock), когда транзакция A ждет снятия блокировки транзакции B и наоборот. База данных автоматически обнаруживает дедлоки и прерывает одну из транзакций. Приложению приходится повторно выполнять прерванную транзакцию.
Альтернативные варианты блокировок: предикатная и по диапазону значений индекса.
Главный недостаток подхода с двухфазной блокировкой — низкая производительность.
Сериализуемая изоляция снимков состояния
Двухфазная блокировка — это представитель пессимистического подхода к управлению конкурентным доступом. Если что-то может пойти не так, когда другая транзакция что-то делает, то лучше подождать снятия блокировки, прежде чем выполнять какие-либо действия.
А сериализуемая изоляция снимков состояния представляет оптимистический подход. Вместо блокировки в случае потенциально опасных действий транзакции просто продолжают выполняться в надежде, что все будет хорошо. При фиксации транзакции база проверяет, не случилось ли чего-то плохого. Если все-таки случилось, то транзакция прерывается, и ее выполнение приходится повторять еще раз.
Как следует из названия, в этом методе в пределах транзакции все операции чтения выполняются на основе снимка состояния БД. К этому добавляется алгоритм для обнаружения конфликтов и принятия решения о том, какие транзакции прервать.
По сравнению с двухфазной блокировкой метод сериализуемой изоляции снимков состояния намного более производительный, так как в нем меньше блокировок и ожиданий. Также у него нет ограничений использования одного ядра процессора, как у однопоточного подхода.
Конечно, даже при сериализуемой изоляции снимков состояния транзакции желательно делать короткими, чтобы снизить риски конфликтов и прерываний.
#кабанчик #сисдиз
Post #107
1.66K
- 👍 18
- ❤ 8
- 🔥 2