|
3 | 3 | * snapmgr.c
|
4 | 4 | * PostgreSQL snapshot manager
|
5 | 5 | *
|
| 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 | + * |
6 | 20 | * We keep track of snapshots in two ways: those "registered" by resowner.c,
|
7 | 21 | * and the "active snapshot" stack. All snapshots in either of them live in
|
8 | 22 | * persistent memory. When a snapshot is no longer in any of these lists
|
9 | 23 | * (tracked by separate refcounts on each snapshot), its memory can be freed.
|
10 | 24 | *
|
| 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 | + * |
11 | 70 | * The FirstXactSnapshot, if any, is treated a bit specially: we increment its
|
12 | 71 | * regd_count and list it in RegisteredSnapshots, but this reference is not
|
13 | 72 | * tracked by a resource owner. We used to use the TopTransactionResourceOwner
|
|
0 commit comments