PostgreSQL Source Code git master
Loading...
Searching...
No Matches
transam.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * transam.c
4 * postgres transaction (commit) log interface routines
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/access/transam/transam.c
12 *
13 * NOTES
14 * This file contains the high level access-method interface to the
15 * transaction system.
16 *
17 *-------------------------------------------------------------------------
18 */
19
20#include "postgres.h"
21
22#include "access/clog.h"
23#include "access/subtrans.h"
24#include "access/transam.h"
25#include "utils/snapmgr.h"
26
27/*
28 * Single-item cache for results of TransactionLogFetch. It's worth having
29 * such a cache because we frequently find ourselves repeatedly checking the
30 * same XID, for example when scanning a table just after a bulk insert,
31 * update, or delete.
32 */
36
37/* Local functions */
39
40
41/* ----------------------------------------------------------------
42 * Postgres log access method interface
43 *
44 * TransactionLogFetch
45 * ----------------------------------------------------------------
46 */
47
48/*
49 * TransactionLogFetch --- fetch commit status of specified transaction id
50 */
51static XidStatus
53{
56
57 /*
58 * Before going to the commit log manager, check our single item cache to
59 * see if we didn't just check the transaction status a moment ago.
60 */
63
64 /*
65 * Also, check to see if the transaction ID is a permanent one.
66 */
68 {
74 }
75
76 /*
77 * Get the transaction status.
78 */
80
81 /*
82 * Cache it, but DO NOT cache status for unfinished or sub-committed
83 * transactions! We only cache status that is guaranteed not to change.
84 */
87 {
91 }
92
93 return xidstatus;
94}
95
96/* ----------------------------------------------------------------
97 * Interface functions
98 *
99 * TransactionIdDidCommit
100 * TransactionIdDidAbort
101 * ========
102 * these functions test the transaction status of
103 * a specified transaction id.
104 *
105 * TransactionIdCommitTree
106 * TransactionIdAsyncCommitTree
107 * TransactionIdAbortTree
108 * ========
109 * these functions set the transaction status of the specified
110 * transaction tree.
111 *
112 * See also TransactionIdIsInProgress, which once was in this module
113 * but now lives in procarray.c, as well as comments at the top of
114 * heapam_visibility.c that explain how everything fits together.
115 * ----------------------------------------------------------------
116 */
117
118/*
119 * TransactionIdDidCommit
120 * True iff transaction associated with the identifier did commit.
121 *
122 * Note:
123 * Assumes transaction identifier is valid and exists in clog.
124 */
125bool /* true if given transaction committed */
127{
129
131
132 /*
133 * If it's marked committed, it's committed.
134 */
136 return true;
137
138 /*
139 * If it's marked subcommitted, we have to check the parent recursively.
140 * However, if it's older than TransactionXmin, we can't look at
141 * pg_subtrans; instead assume that the parent crashed without cleaning up
142 * its children.
143 *
144 * Originally we Assert'ed that the result of SubTransGetParent was not
145 * zero. However with the introduction of prepared transactions, there can
146 * be a window just after database startup where we do not have complete
147 * knowledge in pg_subtrans of the transactions after TransactionXmin.
148 * StartupSUBTRANS() has ensured that any missing information will be
149 * zeroed. Since this case should not happen under normal conditions, it
150 * seems reasonable to emit a WARNING for it.
151 */
153 {
155
157 return false;
160 {
161 elog(WARNING, "no pg_subtrans entry for subcommitted XID %u",
163 return false;
164 }
166 }
167
168 /*
169 * It's not committed.
170 */
171 return false;
172}
173
174/*
175 * TransactionIdDidAbort
176 * True iff transaction associated with the identifier did abort.
177 *
178 * Note:
179 * Assumes transaction identifier is valid and exists in clog.
180 *
181 * Returns true only for explicitly aborted transactions, as transactions
182 * implicitly aborted due to a crash will commonly still appear to be
183 * in-progress in the clog. Most of the time TransactionIdDidCommit(),
184 * with a preceding TransactionIdIsInProgress() check, should be used
185 * instead of TransactionIdDidAbort().
186 */
187bool /* true if given transaction aborted */
189{
191
193
194 /*
195 * If it's marked aborted, it's aborted.
196 */
198 return true;
199
200 /*
201 * If it's marked subcommitted, we have to check the parent recursively.
202 * However, if it's older than TransactionXmin, we can't look at
203 * pg_subtrans; instead assume that the parent crashed without cleaning up
204 * its children.
205 */
207 {
209
211 return true;
214 {
215 /* see notes in TransactionIdDidCommit */
216 elog(WARNING, "no pg_subtrans entry for subcommitted XID %u",
218 return true;
219 }
221 }
222
223 /*
224 * It's not aborted.
225 */
226 return false;
227}
228
229/*
230 * TransactionIdCommitTree
231 * Marks the given transaction and children as committed
232 *
233 * "xid" is a toplevel transaction commit, and the xids array contains its
234 * committed subtransactions.
235 *
236 * This commit operation is not guaranteed to be atomic, but if not, subxids
237 * are correctly marked subcommit first.
238 */
239void
246
247/*
248 * TransactionIdAsyncCommitTree
249 * Same as above, but for async commits. The commit record LSN is needed.
250 */
251void
258
259/*
260 * TransactionIdAbortTree
261 * Marks the given transaction and children as aborted.
262 *
263 * "xid" is a toplevel transaction commit, and the xids array contains its
264 * committed subtransactions.
265 *
266 * We don't need to worry about the non-atomic behavior, since any onlookers
267 * will consider all the xacts as not-yet-committed anyway.
268 */
269void
275
276
277/*
278 * TransactionIdLatest --- get latest XID among a main xact and its children
279 */
282 int nxids, const TransactionId *xids)
283{
284 TransactionId result;
285
286 /*
287 * In practice it is highly likely that the xids[] array is sorted, and so
288 * we could save some cycles by just taking the last child XID, but this
289 * probably isn't so performance-critical that it's worth depending on
290 * that assumption. But just to show we're not totally stupid, scan the
291 * array back-to-front to avoid useless assignments.
292 */
293 result = mainxid;
294 while (--nxids >= 0)
295 {
296 if (TransactionIdPrecedes(result, xids[nxids]))
297 result = xids[nxids];
298 }
299 return result;
300}
301
302
303/*
304 * TransactionIdGetCommitLSN
305 *
306 * This function returns an LSN that is late enough to be able
307 * to guarantee that if we flush up to the LSN returned then we
308 * will have flushed the transaction's commit record to disk.
309 *
310 * The result is not necessarily the exact LSN of the transaction's
311 * commit record! For example, for long-past transactions (those whose
312 * clog pages already migrated to disk), we'll return InvalidXLogRecPtr.
313 * Also, because we group transactions on the same clog page to conserve
314 * storage, we might return the LSN of a later transaction that falls into
315 * the same group.
316 */
319{
320 XLogRecPtr result;
321
322 /*
323 * Currently, all uses of this function are for xids that were just
324 * reported to be committed by TransactionLogFetch, so we expect that
325 * checking TransactionLogFetch's cache will usually succeed and avoid an
326 * extra trip to shared memory.
327 */
329 return cachedCommitLSN;
330
331 /* Special XIDs are always known committed */
332 if (!TransactionIdIsNormal(xid))
333 return InvalidXLogRecPtr;
334
335 /*
336 * Get the transaction status.
337 */
338 (void) TransactionIdGetStatus(xid, &result);
339
340 return result;
341}
uint32 TransactionId
Definition c.h:666
XidStatus TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn)
Definition clog.c:734
void TransactionIdSetTreeStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn)
Definition clog.c:181
#define TRANSACTION_STATUS_IN_PROGRESS
Definition clog.h:27
int XidStatus
Definition clog.h:25
#define TRANSACTION_STATUS_ABORTED
Definition clog.h:29
#define TRANSACTION_STATUS_SUB_COMMITTED
Definition clog.h:30
#define TRANSACTION_STATUS_COMMITTED
Definition clog.h:28
#define WARNING
Definition elog.h:36
#define elog(elevel,...)
Definition elog.h:226
static int fb(int x)
TransactionId TransactionXmin
Definition snapmgr.c:159
TransactionId SubTransGetParent(TransactionId xid)
Definition subtrans.c:121
void TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids, XLogRecPtr lsn)
Definition transam.c:252
static TransactionId cachedFetchXid
Definition transam.c:33
static XidStatus TransactionLogFetch(TransactionId transactionId)
Definition transam.c:52
TransactionId TransactionIdLatest(TransactionId mainxid, int nxids, const TransactionId *xids)
Definition transam.c:281
bool TransactionIdDidCommit(TransactionId transactionId)
Definition transam.c:126
void TransactionIdCommitTree(TransactionId xid, int nxids, TransactionId *xids)
Definition transam.c:240
void TransactionIdAbortTree(TransactionId xid, int nxids, TransactionId *xids)
Definition transam.c:270
bool TransactionIdDidAbort(TransactionId transactionId)
Definition transam.c:188
XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid)
Definition transam.c:318
static XLogRecPtr cachedCommitLSN
Definition transam.c:35
static XidStatus cachedFetchXidStatus
Definition transam.c:34
#define FrozenTransactionId
Definition transam.h:33
#define InvalidTransactionId
Definition transam.h:31
#define TransactionIdEquals(id1, id2)
Definition transam.h:43
#define BootstrapTransactionId
Definition transam.h:32
#define TransactionIdIsValid(xid)
Definition transam.h:41
#define TransactionIdIsNormal(xid)
Definition transam.h:42
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition transam.h:263
uint64 XLogRecPtr
Definition xlogdefs.h:21
#define InvalidXLogRecPtr
Definition xlogdefs.h:28