Skip to content

Commit 043745c

Browse files
committed
Improve snapmgr.c comment
Add more details on the different kinds of snapshots, how to use them, and how the active snapshot stack works. Discussion: https://www.postgresql.org/message-id/[email protected]
1 parent 8076c00 commit 043745c

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

src/backend/utils/time/snapmgr.c

+59
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,70 @@
33
* snapmgr.c
44
* PostgreSQL snapshot manager
55
*
6+
* The following functions return an MVCC snapshot that can be used in tuple
7+
* visibility checks:
8+
*
9+
* - GetTransactionSnapshot
10+
* - GetLatestSnapshot
11+
* - GetCatalogSnapshot
12+
* - GetNonHistoricCatalogSnapshot
13+
*
14+
* Each of these functions returns a reference to a statically allocated
15+
* snapshot. The statically allocated snapshot is subject to change on any
16+
* snapshot-related function call, and should not be used directly. Instead,
17+
* call PushActiveSnapshot() or RegisterSnapshot() to create a longer-lived
18+
* copy and use that.
19+
*
620
* We keep track of snapshots in two ways: those "registered" by resowner.c,
721
* and the "active snapshot" stack. All snapshots in either of them live in
822
* persistent memory. When a snapshot is no longer in any of these lists
923
* (tracked by separate refcounts on each snapshot), its memory can be freed.
1024
*
25+
* In addition to the above-mentioned MVCC snapshots, there are some special
26+
* snapshots like SnapshotSelf, SnapshotAny, and "dirty" snapshots. They can
27+
* only be used in limited contexts and cannot be registered or pushed to the
28+
* active stack.
29+
*
30+
* ActiveSnapshot stack
31+
* --------------------
32+
*
33+
* Most visibility checks use the current "active snapshot" returned by
34+
* GetActiveSnapshot(). When running normal queries, the active snapshot is
35+
* set when query execution begins based on the transaction isolation level.
36+
*
37+
* The active snapshot is tracked in a stack so that the currently active one
38+
* is at the top of the stack. It mirrors the process call stack: whenever we
39+
* recurse or switch context to fetch rows from a different portal for
40+
* example, the appropriate snapshot is pushed to become the active snapshot,
41+
* and popped on return. Once upon a time, ActiveSnapshot was just a global
42+
* variable that was saved and restored similar to CurrentMemoryContext, but
43+
* nowadays it's managed as a separate data structure so that we can keep
44+
* track of which snapshots are in use and reset MyProc->xmin when there is no
45+
* active snapshot.
46+
*
47+
* However, there are a couple of exceptions where the active snapshot stack
48+
* does not strictly mirror the call stack:
49+
*
50+
* - VACUUM and a few other utility commands manage their own transactions,
51+
* which take their own snapshots. They are called with an active snapshot
52+
* set, like most utility commands, but they pop the active snapshot that
53+
* was pushed by the caller. PortalRunUtility knows about the possibility
54+
* that the snapshot it pushed is no longer active on return.
55+
*
56+
* - When COMMIT or ROLLBACK is executed within a procedure or DO-block, the
57+
* active snapshot stack is destroyed, and re-established later when
58+
* subsequent statements in the procedure are executed. There are many
59+
* limitations on when in-procedure COMMIT/ROLLBACK is allowed; one such
60+
* limitation is that all the snapshots on the active snapshot stack are
61+
* known to portals that are being executed, which makes it safe to reset
62+
* the stack. See EnsurePortalSnapshotExists().
63+
*
64+
* Registered snapshots
65+
* --------------------
66+
*
67+
* In addition to snapshots pushed to the active snapshot stack, a snapshot
68+
* can be registered with a resource owner.
69+
*
1170
* The FirstXactSnapshot, if any, is treated a bit specially: we increment its
1271
* regd_count and list it in RegisteredSnapshots, but this reference is not
1372
* tracked by a resource owner. We used to use the TopTransactionResourceOwner

0 commit comments

Comments
 (0)