mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
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/7c56f180-b9e1-481e-8c1d-efa63de3ecbb@iki.fi
This commit is contained in:
parent
8076c00592
commit
043745c3a0
@ -3,11 +3,70 @@
|
||||
* snapmgr.c
|
||||
* PostgreSQL snapshot manager
|
||||
*
|
||||
* The following functions return an MVCC snapshot that can be used in tuple
|
||||
* visibility checks:
|
||||
*
|
||||
* - GetTransactionSnapshot
|
||||
* - GetLatestSnapshot
|
||||
* - GetCatalogSnapshot
|
||||
* - GetNonHistoricCatalogSnapshot
|
||||
*
|
||||
* Each of these functions returns a reference to a statically allocated
|
||||
* snapshot. The statically allocated snapshot is subject to change on any
|
||||
* snapshot-related function call, and should not be used directly. Instead,
|
||||
* call PushActiveSnapshot() or RegisterSnapshot() to create a longer-lived
|
||||
* copy and use that.
|
||||
*
|
||||
* We keep track of snapshots in two ways: those "registered" by resowner.c,
|
||||
* and the "active snapshot" stack. All snapshots in either of them live in
|
||||
* persistent memory. When a snapshot is no longer in any of these lists
|
||||
* (tracked by separate refcounts on each snapshot), its memory can be freed.
|
||||
*
|
||||
* In addition to the above-mentioned MVCC snapshots, there are some special
|
||||
* snapshots like SnapshotSelf, SnapshotAny, and "dirty" snapshots. They can
|
||||
* only be used in limited contexts and cannot be registered or pushed to the
|
||||
* active stack.
|
||||
*
|
||||
* ActiveSnapshot stack
|
||||
* --------------------
|
||||
*
|
||||
* Most visibility checks use the current "active snapshot" returned by
|
||||
* GetActiveSnapshot(). When running normal queries, the active snapshot is
|
||||
* set when query execution begins based on the transaction isolation level.
|
||||
*
|
||||
* The active snapshot is tracked in a stack so that the currently active one
|
||||
* is at the top of the stack. It mirrors the process call stack: whenever we
|
||||
* recurse or switch context to fetch rows from a different portal for
|
||||
* example, the appropriate snapshot is pushed to become the active snapshot,
|
||||
* and popped on return. Once upon a time, ActiveSnapshot was just a global
|
||||
* variable that was saved and restored similar to CurrentMemoryContext, but
|
||||
* nowadays it's managed as a separate data structure so that we can keep
|
||||
* track of which snapshots are in use and reset MyProc->xmin when there is no
|
||||
* active snapshot.
|
||||
*
|
||||
* However, there are a couple of exceptions where the active snapshot stack
|
||||
* does not strictly mirror the call stack:
|
||||
*
|
||||
* - VACUUM and a few other utility commands manage their own transactions,
|
||||
* which take their own snapshots. They are called with an active snapshot
|
||||
* set, like most utility commands, but they pop the active snapshot that
|
||||
* was pushed by the caller. PortalRunUtility knows about the possibility
|
||||
* that the snapshot it pushed is no longer active on return.
|
||||
*
|
||||
* - When COMMIT or ROLLBACK is executed within a procedure or DO-block, the
|
||||
* active snapshot stack is destroyed, and re-established later when
|
||||
* subsequent statements in the procedure are executed. There are many
|
||||
* limitations on when in-procedure COMMIT/ROLLBACK is allowed; one such
|
||||
* limitation is that all the snapshots on the active snapshot stack are
|
||||
* known to portals that are being executed, which makes it safe to reset
|
||||
* the stack. See EnsurePortalSnapshotExists().
|
||||
*
|
||||
* Registered snapshots
|
||||
* --------------------
|
||||
*
|
||||
* In addition to snapshots pushed to the active snapshot stack, a snapshot
|
||||
* can be registered with a resource owner.
|
||||
*
|
||||
* The FirstXactSnapshot, if any, is treated a bit specially: we increment its
|
||||
* regd_count and list it in RegisteredSnapshots, but this reference is not
|
||||
* tracked by a resource owner. We used to use the TopTransactionResourceOwner
|
||||
|
Loading…
x
Reference in New Issue
Block a user