Правила проверки видимости PostgreSQL
PostgreSQL правила проверки видимости используются для определения того, какие версии данных являются видимыми в транзакционном снимке. Эти правила гарантируют, что каждая транзакция видит согласованный снимок базы данных, полученный на время начала транзакции.
Эти правила слишком сложны для подробного объяснения. Поэтому в данном документе мы рассматриваем минимальный набор правил, необходимых для понимания последующих разделов.
Всего существует 10 правил проверки видимости. Их можно разделить на три категории.
Состояние транзакции t_xmin - ABORTED
Если статус транзакции t_xmin –ABORTED, она всегда будет невидима (правило 1).
/* t_xmin status == ABORTED */
Rule 1: IF t_xmin status is 'ABORTED' THEN
RETURN 'Invisible'
END IF
Это правило можно представать в виде следующего математического выражения:
- Правило 1: если статус (t_xmin) = ABORTED ⇒⇒ Invisible
Состояние транзакции t_xmin - IN_PROGRESS
Если статус транзакции t_xmin = IN_PROGRESS, то она, по сути, также невидима (правила 3 и 4), за исключением одного условия.
/* t_xmin status == IN_PROGRESS */
IF t_xmin status is 'IN_PROGRESS' THEN
IF t_xmin = current_txid THEN
Rule 2: IF t_xmax = INVALID THEN
RETURN 'Visible'
Rule 3: ELSE /* this tuple has been deleted or updated */
/* by the current transaction itself. */
RETURN 'Invisible'
END IF
Rule 4: ELSE /* t_xmin ≠ current_txid */
RETURN 'Invisible'
END IF
END IF
Если кортеж вставлен другой транзакцией и его статус t_xmin = IN_PROGRESS, то этот кортеж, очевидно, невидим (правило 4).
Если t_xmin эквивалентен текущему txid (т.е. этот кортеж вставлен текущей транзакцией), а t_xmax не является INVALID, то этот кортеж невидим, поскольку он был обновлен или удален текущей транзакцией (правило 3).
Исключением является случай, когда кортеж вставлен текущей транзакцией, а t_xmax = INVALID. В этом случае кортеж должен быть виден текущей транзакции (правило 2), так как данный кортеж является кортежем, вставленным текущей транзакцией.
- Правило 2: If Status(t_xmin) = IN_PROGRESS ∧∧ t_xmin = current_txid ∧∧ t_xmax = INVAILD ⇒⇒ Visible
- Правило 3: If Status(t_xmin) = IN_PROGRESS ∧∧ t_xmin = current_txid ∧∧ t_xmax ≠≠ INVAILD ⇒⇒ Invisible
- Правило 4: If Status(t_xmin) = IN_PROGRESS ∧∧ t_xmin ≠≠ current_txid ⇒⇒ Invisible
Состояние транзакции t_xmin - COMMITTED
Если статус транзакции t_xmin = COMMITTED, то транзакция является видимой (правила 6,8 и 9), за исключением трех случаев.
/* t_xmin status == COMMITTED */
IF t_xmin status is 'COMMITTED' THEN
Rule 5: IF t_xmin is 'active' in the obtained transaction snapshot THEN
RETURN 'Invisible'
Rule 6: ELSE IF t_xmax = INVALID OR status of t_xmax is 'ABORTED' THEN
RETURN 'Visible'
ELSE IF t_xmax status is 'IN_PROGRESS' THEN
Rule 7: IF t_xmax = current_txid THEN
RETURN 'Invisible'
Rule 8: ELSE /* t_xmax != current_txid */
RETURN 'Visible'
END IF
ELSE IF t_xmax status is 'COMMITTED' THEN
Rule 9: IF t_xmax is 'active' in the obtained transaction snapshot THEN
RETURN 'Visible'
Rule 10: ELSE
RETURN 'Invisible'
END IF
END IF
END IF
Правило 6 очевидно, поскольку t_xmax = INVALID или ABORTED. Три исключения и правила 8 - 9 можно представить следующим образом:
Первое исключение заключается в том, что t_xmin является активным в полученном моментальном снимке транзакции (правило 5). При выполнении такого условия этот кортеж является невидимым, поскольку t_xmin рассматривается как IN_PROGRESS.
Вторым исключением является то, что t_xmax = текущему txid (правило 7). В данном случае, как и в правиле 3, данный кортеж невидим, поскольку он был обновлен или удален самой транзакцией.
Напротив, если статус t_xmax - IN_PROGRESS и t_xmax не равен текущнму txid (правило 8), кортеж является видимым, поскольку он не был удален.
Третье исключение заключается в том, что статус t_xmax - COMMITTED, а t_xmax не активен в полученном моментальном снимке транзакции (правило 10). В данном случае кортеж невидим, поскольку он был обновлен или удален другой транзакцией.
Напротив, если статус t_xmax - COMMITTED, при этом t_xmax активен в полученном моментальном снимке транзакции (правило 9), кортеж будет виден, потому что t_xmax должен рассматриваться как IN_PROGRESS.
- Правило 5: If Status(t_xmin) = COMMITTED ∧∧ Snapshot(t_xmin) = active ⇒⇒ Invisible
- Правило 6: If Status(t_xmin) = COMMITTED ∧∧ (t_xmax = INVALID ∨∨ Status(t_xmax) = ABORTED) ⇒⇒ Visible
- Правило 7: If Status(t_xmin) = COMMITTED ∧∧ Status(t_xmax) = IN_PROGRESS ∧∧ t_xmax = current_txid ⇒⇒ Invisible
- Правило 8: If Status(t_xmin) = COMMITTED ∧∧ Status(t_xmax) = IN_PROGRESS ∧∧ t_xmax ≠≠ current_txid ⇒⇒ Visible
- Правило 9: If Status(t_xmin) = COMMITTED ∧∧ Status(t_xmax) = COMMITTED ∧∧ Snapshot(t_xmax) = active ⇒⇒ Visible
- Правило 10: If Status(t_xmin) = COMMITTED ∧∧ Status(t_xmax) = COMMITTED ∧∧ Snapshot(t_xmax) ≠≠ active ⇒⇒ Invisible



