Postgres Professional corporate blog
PostgreSQL
SQL
Comments 11
+1
Егор, большое спасибо за статью!

Традиционно, несколько вопросов:

№1.
На уровне изоляции Read Committed снимок создается в начале каждого оператора транзакции. Такой снимок активен, пока выполняется оператор.


То есть имеем операции «создания»/«удаления» снимка. Их тем больше, чем больше операторов в транзакции

На уровнях Repeatable Read и Serializable снимок создается один раз в начале первого оператора транзакции. Такой снимок остается активным до самого конца транзакции.


То есть имеем всего одну операцию «создания»/«удаления» снимка.

Сам вопрос: Насколько затратны операции «создания»/«удаления»? Можно ли сказать, что уровни Repeatable Read и Serializable
значительно меньше нагружают сервер БД? Или разница ничтожно мала по сравнению с другими действиями для этих транзакций? Я имею ввиду порядки затрат, соизмеримые с порядками затрат оптимизатора, то есть микросекунды. Понятно, что по сравнению с IO операциями передачи данных по сети эти затраты будут ничтожно малы.

Имеется ввиду затратность по:
* RAM — насколько «тяжеловесна» информация о снимке.
* CPU/IO — насколько трудоемко создавать новые снимки (и видимо помечать неактивные к удалению).

№2.
На уровне изоляции Read Committed снимок создается в начале каждого оператора транзакции. Такой снимок активен, пока выполняется оператор.


Что означает понятие «снимок активен» в применении к Read Committed? Это означает, что при создании нового снимка, ранее созданный (например, на момент создания транзакции) уже никак не участвует в транзакции? Как удаляются такие снимки? Они помечаются к удалению или удаляются в рамках той же транзакции?

№3
такие интервалы не пересекаются, поэтому одна строка представлена в любом снимке максимум одной своей версией.


То есть невозможна ситуация, при которой xmin xmax одной и той же строки будут перезаписаны в разных транзакциях? То есть если xmin/xmax когда-либо были записаны — измениться они уже не могут (immutable). При условии, если транзакция изменившая их первой — зафиксировалась.

№4
А для DDL-запросов (тоже транзакционны) изоляции и снимки тоже используются? Насколько механизмы изоляций и снимков отличаются от уже описанных механизмов в этой и в предыдущих статьях?
0
За Serializable Snapshot Isolation(SSI) мы расплачиваемся раздуванием таблиц и autovacuum.
0
Ну, не совсем. Расплачиваемся мы не за SSI, а за SI (Serializable в этом смысле ничего нового не дает). И даже не за сам SI, а за его реализацию со сборкой мусора.
Есть реализации, которые этим не страдают (как в Оракле, или вот zheap). Но zheap — это пока эксперимент, о нем рановато говорить.
+1
Владимир, спасибо. По порядку.
1.
Разницу можно считать ничтожно малой. Это точно не повод задумываться о Repeatable Read (таким поводом должна быть изоляция).
Информация о снимке — это всего несколько чисел, ничего тяжелого. Самое неприятное, с чем там приходится иметь дело — это чтение ProcArray для того, чтобы запомнить список активных транзакций. Это требует блокировки, хоть и разделяемой. Так что при увеличении количества соединений (больше нескольких сотен) ProcArray начинает становиться узким местом, и надо думать о пуле соединений.
0

Спасибо, а как пул соединений поможет в данном случае? Насколько я понял, источник информации о состоянии транзакций «один на всех»

0
Просто соединений (и, следовательно, одновременных транзакций) будет меньше. Толкотня за ProcArray уменьшится.
+1
2.
На каком-то уровне абстракции (достаточном для понимания происходящего) можно просто считать, что снимок живет столько, сколько запрос/транзакция, и потом исчезает.
Если влезать глубже, то начинаются всякие детали, в которых легко погрязнуть. Если прям хочется копнуть, то можно начинать с src/backend/utils/time/snapmgr.c. Но не уверен, что это сильно полезно.
+1
3.
Одну и ту же строку две разные транзакции не могут изменять одновременно; одна из них будет заблокирована. Ну и в целом версии идут одна за другой — одна стала неактуальной, появилась другая актуальная, xmax одной будет равен xmin другой.
+1
4.
DDL — это по сути изменение таблиц системного каталога. Для системного каталога тоже используется многоверсионность и снимки, это и дает нам транзакционный DDL. Но отличия все же есть.
Внешне все выглядит так, как будто для таблиц системного каталога всегда действует уровень Repeatable Read, даже на Read Committed.
Но я в это глубоко не влезал, а надо бы. Так что за этот вопрос отдельное спасибо, поизучаю.
Only those users with full accounts are able to leave comments. , please.