1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * xact.h |
4 | * postgres transaction system definitions |
5 | * |
6 | * |
7 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
8 | * Portions Copyright (c) 1994, Regents of the University of California |
9 | * |
10 | * src/include/access/xact.h |
11 | * |
12 | *------------------------------------------------------------------------- |
13 | */ |
14 | #ifndef XACT_H |
15 | #define XACT_H |
16 | |
17 | #include "access/transam.h" |
18 | #include "access/xlogreader.h" |
19 | #include "lib/stringinfo.h" |
20 | #include "nodes/pg_list.h" |
21 | #include "storage/relfilenode.h" |
22 | #include "storage/sinval.h" |
23 | #include "utils/datetime.h" |
24 | |
25 | /* |
26 | * Maximum size of Global Transaction ID (including '\0'). |
27 | * |
28 | * Note that the max value of GIDSIZE must fit in the uint16 gidlen, |
29 | * specified in TwoPhaseFileHeader. |
30 | */ |
31 | #define GIDSIZE 200 |
32 | |
33 | /* |
34 | * Xact isolation levels |
35 | */ |
36 | #define XACT_READ_UNCOMMITTED 0 |
37 | #define XACT_READ_COMMITTED 1 |
38 | #define XACT_REPEATABLE_READ 2 |
39 | #define XACT_SERIALIZABLE 3 |
40 | |
41 | extern int DefaultXactIsoLevel; |
42 | extern PGDLLIMPORT int XactIsoLevel; |
43 | |
44 | /* |
45 | * We implement three isolation levels internally. |
46 | * The two stronger ones use one snapshot per database transaction; |
47 | * the others use one snapshot per statement. |
48 | * Serializable uses predicate locks in addition to snapshots. |
49 | * These macros should be used to check which isolation level is selected. |
50 | */ |
51 | #define IsolationUsesXactSnapshot() (XactIsoLevel >= XACT_REPEATABLE_READ) |
52 | #define IsolationIsSerializable() (XactIsoLevel == XACT_SERIALIZABLE) |
53 | |
54 | /* Xact read-only state */ |
55 | extern bool DefaultXactReadOnly; |
56 | extern bool XactReadOnly; |
57 | |
58 | /* flag for logging statements in this transaction */ |
59 | extern bool xact_is_sampled; |
60 | |
61 | /* |
62 | * Xact is deferrable -- only meaningful (currently) for read only |
63 | * SERIALIZABLE transactions |
64 | */ |
65 | extern bool DefaultXactDeferrable; |
66 | extern bool XactDeferrable; |
67 | |
68 | typedef enum |
69 | { |
70 | SYNCHRONOUS_COMMIT_OFF, /* asynchronous commit */ |
71 | SYNCHRONOUS_COMMIT_LOCAL_FLUSH, /* wait for local flush only */ |
72 | SYNCHRONOUS_COMMIT_REMOTE_WRITE, /* wait for local flush and remote |
73 | * write */ |
74 | SYNCHRONOUS_COMMIT_REMOTE_FLUSH, /* wait for local and remote flush */ |
75 | SYNCHRONOUS_COMMIT_REMOTE_APPLY /* wait for local flush and remote apply */ |
76 | } SyncCommitLevel; |
77 | |
78 | /* Define the default setting for synchronous_commit */ |
79 | #define SYNCHRONOUS_COMMIT_ON SYNCHRONOUS_COMMIT_REMOTE_FLUSH |
80 | |
81 | /* Synchronous commit level */ |
82 | extern int synchronous_commit; |
83 | |
84 | /* |
85 | * Miscellaneous flag bits to record events which occur on the top level |
86 | * transaction. These flags are only persisted in MyXactFlags and are intended |
87 | * so we remember to do certain things later in the transaction. This is |
88 | * globally accessible, so can be set from anywhere in the code which requires |
89 | * recording flags. |
90 | */ |
91 | extern int MyXactFlags; |
92 | |
93 | /* |
94 | * XACT_FLAGS_ACCESSEDTEMPNAMESPACE - set when a temporary object is accessed. |
95 | * We don't allow PREPARE TRANSACTION in that case. |
96 | */ |
97 | #define XACT_FLAGS_ACCESSEDTEMPNAMESPACE (1U << 0) |
98 | |
99 | /* |
100 | * XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK - records whether the top level xact |
101 | * logged any Access Exclusive Locks. |
102 | */ |
103 | #define XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK (1U << 1) |
104 | |
105 | /* |
106 | * start- and end-of-transaction callbacks for dynamically loaded modules |
107 | */ |
108 | typedef enum |
109 | { |
110 | XACT_EVENT_COMMIT, |
111 | XACT_EVENT_PARALLEL_COMMIT, |
112 | XACT_EVENT_ABORT, |
113 | XACT_EVENT_PARALLEL_ABORT, |
114 | XACT_EVENT_PREPARE, |
115 | XACT_EVENT_PRE_COMMIT, |
116 | XACT_EVENT_PARALLEL_PRE_COMMIT, |
117 | XACT_EVENT_PRE_PREPARE |
118 | } XactEvent; |
119 | |
120 | typedef void (*XactCallback) (XactEvent event, void *arg); |
121 | |
122 | typedef enum |
123 | { |
124 | SUBXACT_EVENT_START_SUB, |
125 | SUBXACT_EVENT_COMMIT_SUB, |
126 | SUBXACT_EVENT_ABORT_SUB, |
127 | SUBXACT_EVENT_PRE_COMMIT_SUB |
128 | } SubXactEvent; |
129 | |
130 | typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid, |
131 | SubTransactionId parentSubid, void *arg); |
132 | |
133 | |
134 | /* ---------------- |
135 | * transaction-related XLOG entries |
136 | * ---------------- |
137 | */ |
138 | |
139 | /* |
140 | * XLOG allows to store some information in high 4 bits of log record xl_info |
141 | * field. We use 3 for the opcode, and one about an optional flag variable. |
142 | */ |
143 | #define XLOG_XACT_COMMIT 0x00 |
144 | #define XLOG_XACT_PREPARE 0x10 |
145 | #define XLOG_XACT_ABORT 0x20 |
146 | #define XLOG_XACT_COMMIT_PREPARED 0x30 |
147 | #define XLOG_XACT_ABORT_PREPARED 0x40 |
148 | #define XLOG_XACT_ASSIGNMENT 0x50 |
149 | /* free opcode 0x60 */ |
150 | /* free opcode 0x70 */ |
151 | |
152 | /* mask for filtering opcodes out of xl_info */ |
153 | #define XLOG_XACT_OPMASK 0x70 |
154 | |
155 | /* does this record have a 'xinfo' field or not */ |
156 | #define XLOG_XACT_HAS_INFO 0x80 |
157 | |
158 | /* |
159 | * The following flags, stored in xinfo, determine which information is |
160 | * contained in commit/abort records. |
161 | */ |
162 | #define XACT_XINFO_HAS_DBINFO (1U << 0) |
163 | #define XACT_XINFO_HAS_SUBXACTS (1U << 1) |
164 | #define XACT_XINFO_HAS_RELFILENODES (1U << 2) |
165 | #define XACT_XINFO_HAS_INVALS (1U << 3) |
166 | #define XACT_XINFO_HAS_TWOPHASE (1U << 4) |
167 | #define XACT_XINFO_HAS_ORIGIN (1U << 5) |
168 | #define XACT_XINFO_HAS_AE_LOCKS (1U << 6) |
169 | #define XACT_XINFO_HAS_GID (1U << 7) |
170 | |
171 | /* |
172 | * Also stored in xinfo, these indicating a variety of additional actions that |
173 | * need to occur when emulating transaction effects during recovery. |
174 | * |
175 | * They are named XactCompletion... to differentiate them from |
176 | * EOXact... routines which run at the end of the original transaction |
177 | * completion. |
178 | */ |
179 | #define XACT_COMPLETION_APPLY_FEEDBACK (1U << 29) |
180 | #define XACT_COMPLETION_UPDATE_RELCACHE_FILE (1U << 30) |
181 | #define XACT_COMPLETION_FORCE_SYNC_COMMIT (1U << 31) |
182 | |
183 | /* Access macros for above flags */ |
184 | #define XactCompletionApplyFeedback(xinfo) \ |
185 | ((xinfo & XACT_COMPLETION_APPLY_FEEDBACK) != 0) |
186 | #define XactCompletionRelcacheInitFileInval(xinfo) \ |
187 | ((xinfo & XACT_COMPLETION_UPDATE_RELCACHE_FILE) != 0) |
188 | #define XactCompletionForceSyncCommit(xinfo) \ |
189 | ((xinfo & XACT_COMPLETION_FORCE_SYNC_COMMIT) != 0) |
190 | |
191 | typedef struct xl_xact_assignment |
192 | { |
193 | TransactionId xtop; /* assigned XID's top-level XID */ |
194 | int nsubxacts; /* number of subtransaction XIDs */ |
195 | TransactionId xsub[FLEXIBLE_ARRAY_MEMBER]; /* assigned subxids */ |
196 | } xl_xact_assignment; |
197 | |
198 | #define MinSizeOfXactAssignment offsetof(xl_xact_assignment, xsub) |
199 | |
200 | /* |
201 | * Commit and abort records can contain a lot of information. But a large |
202 | * portion of the records won't need all possible pieces of information. So we |
203 | * only include what's needed. |
204 | * |
205 | * A minimal commit/abort record only consists of a xl_xact_commit/abort |
206 | * struct. The presence of additional information is indicated by bits set in |
207 | * 'xl_xact_xinfo->xinfo'. The presence of the xinfo field itself is signalled |
208 | * by a set XLOG_XACT_HAS_INFO bit in the xl_info field. |
209 | * |
210 | * NB: All the individual data chunks should be sized to multiples of |
211 | * sizeof(int) and only require int32 alignment. If they require bigger |
212 | * alignment, they need to be copied upon reading. |
213 | */ |
214 | |
215 | /* sub-records for commit/abort */ |
216 | |
217 | typedef struct xl_xact_xinfo |
218 | { |
219 | /* |
220 | * Even though we right now only require 1 byte of space in xinfo we use |
221 | * four so following records don't have to care about alignment. Commit |
222 | * records can be large, so copying large portions isn't attractive. |
223 | */ |
224 | uint32 xinfo; |
225 | } xl_xact_xinfo; |
226 | |
227 | typedef struct xl_xact_dbinfo |
228 | { |
229 | Oid dbId; /* MyDatabaseId */ |
230 | Oid tsId; /* MyDatabaseTableSpace */ |
231 | } xl_xact_dbinfo; |
232 | |
233 | typedef struct xl_xact_subxacts |
234 | { |
235 | int nsubxacts; /* number of subtransaction XIDs */ |
236 | TransactionId subxacts[FLEXIBLE_ARRAY_MEMBER]; |
237 | } xl_xact_subxacts; |
238 | #define MinSizeOfXactSubxacts offsetof(xl_xact_subxacts, subxacts) |
239 | |
240 | typedef struct xl_xact_relfilenodes |
241 | { |
242 | int nrels; /* number of subtransaction XIDs */ |
243 | RelFileNode xnodes[FLEXIBLE_ARRAY_MEMBER]; |
244 | } xl_xact_relfilenodes; |
245 | #define MinSizeOfXactRelfilenodes offsetof(xl_xact_relfilenodes, xnodes) |
246 | |
247 | typedef struct xl_xact_invals |
248 | { |
249 | int nmsgs; /* number of shared inval msgs */ |
250 | SharedInvalidationMessage msgs[FLEXIBLE_ARRAY_MEMBER]; |
251 | } xl_xact_invals; |
252 | #define MinSizeOfXactInvals offsetof(xl_xact_invals, msgs) |
253 | |
254 | typedef struct xl_xact_twophase |
255 | { |
256 | TransactionId xid; |
257 | } xl_xact_twophase; |
258 | |
259 | typedef struct xl_xact_origin |
260 | { |
261 | XLogRecPtr origin_lsn; |
262 | TimestampTz origin_timestamp; |
263 | } xl_xact_origin; |
264 | |
265 | typedef struct xl_xact_commit |
266 | { |
267 | TimestampTz xact_time; /* time of commit */ |
268 | |
269 | /* xl_xact_xinfo follows if XLOG_XACT_HAS_INFO */ |
270 | /* xl_xact_dbinfo follows if XINFO_HAS_DBINFO */ |
271 | /* xl_xact_subxacts follows if XINFO_HAS_SUBXACT */ |
272 | /* xl_xact_relfilenodes follows if XINFO_HAS_RELFILENODES */ |
273 | /* xl_xact_invals follows if XINFO_HAS_INVALS */ |
274 | /* xl_xact_twophase follows if XINFO_HAS_TWOPHASE */ |
275 | /* twophase_gid follows if XINFO_HAS_GID. As a null-terminated string. */ |
276 | /* xl_xact_origin follows if XINFO_HAS_ORIGIN, stored unaligned! */ |
277 | } xl_xact_commit; |
278 | #define MinSizeOfXactCommit (offsetof(xl_xact_commit, xact_time) + sizeof(TimestampTz)) |
279 | |
280 | typedef struct xl_xact_abort |
281 | { |
282 | TimestampTz xact_time; /* time of abort */ |
283 | |
284 | /* xl_xact_xinfo follows if XLOG_XACT_HAS_INFO */ |
285 | /* xl_xact_dbinfo follows if XINFO_HAS_DBINFO */ |
286 | /* xl_xact_subxacts follows if HAS_SUBXACT */ |
287 | /* xl_xact_relfilenodes follows if HAS_RELFILENODES */ |
288 | /* No invalidation messages needed. */ |
289 | /* xl_xact_twophase follows if XINFO_HAS_TWOPHASE */ |
290 | /* twophase_gid follows if XINFO_HAS_GID. As a null-terminated string. */ |
291 | /* xl_xact_origin follows if XINFO_HAS_ORIGIN, stored unaligned! */ |
292 | } xl_xact_abort; |
293 | #define MinSizeOfXactAbort sizeof(xl_xact_abort) |
294 | |
295 | /* |
296 | * Commit/Abort records in the above form are a bit verbose to parse, so |
297 | * there's a deconstructed versions generated by ParseCommit/AbortRecord() for |
298 | * easier consumption. |
299 | */ |
300 | typedef struct xl_xact_parsed_commit |
301 | { |
302 | TimestampTz xact_time; |
303 | uint32 xinfo; |
304 | |
305 | Oid dbId; /* MyDatabaseId */ |
306 | Oid tsId; /* MyDatabaseTableSpace */ |
307 | |
308 | int nsubxacts; |
309 | TransactionId *subxacts; |
310 | |
311 | int nrels; |
312 | RelFileNode *xnodes; |
313 | |
314 | int nmsgs; |
315 | SharedInvalidationMessage *msgs; |
316 | |
317 | TransactionId twophase_xid; /* only for 2PC */ |
318 | char twophase_gid[GIDSIZE]; /* only for 2PC */ |
319 | int nabortrels; /* only for 2PC */ |
320 | RelFileNode *abortnodes; /* only for 2PC */ |
321 | |
322 | XLogRecPtr origin_lsn; |
323 | TimestampTz origin_timestamp; |
324 | } xl_xact_parsed_commit; |
325 | |
326 | typedef xl_xact_parsed_commit xl_xact_parsed_prepare; |
327 | |
328 | typedef struct xl_xact_parsed_abort |
329 | { |
330 | TimestampTz xact_time; |
331 | uint32 xinfo; |
332 | |
333 | Oid dbId; /* MyDatabaseId */ |
334 | Oid tsId; /* MyDatabaseTableSpace */ |
335 | |
336 | int nsubxacts; |
337 | TransactionId *subxacts; |
338 | |
339 | int nrels; |
340 | RelFileNode *xnodes; |
341 | |
342 | TransactionId twophase_xid; /* only for 2PC */ |
343 | char twophase_gid[GIDSIZE]; /* only for 2PC */ |
344 | |
345 | XLogRecPtr origin_lsn; |
346 | TimestampTz origin_timestamp; |
347 | } xl_xact_parsed_abort; |
348 | |
349 | |
350 | /* ---------------- |
351 | * extern definitions |
352 | * ---------------- |
353 | */ |
354 | extern bool IsTransactionState(void); |
355 | extern bool IsAbortedTransactionBlockState(void); |
356 | extern TransactionId GetTopTransactionId(void); |
357 | extern TransactionId GetTopTransactionIdIfAny(void); |
358 | extern TransactionId GetCurrentTransactionId(void); |
359 | extern TransactionId GetCurrentTransactionIdIfAny(void); |
360 | extern TransactionId GetStableLatestTransactionId(void); |
361 | extern SubTransactionId GetCurrentSubTransactionId(void); |
362 | extern FullTransactionId GetTopFullTransactionId(void); |
363 | extern FullTransactionId GetTopFullTransactionIdIfAny(void); |
364 | extern FullTransactionId GetCurrentFullTransactionId(void); |
365 | extern FullTransactionId GetCurrentFullTransactionIdIfAny(void); |
366 | extern void MarkCurrentTransactionIdLoggedIfAny(void); |
367 | extern bool SubTransactionIsActive(SubTransactionId subxid); |
368 | extern CommandId GetCurrentCommandId(bool used); |
369 | extern void SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts); |
370 | extern TimestampTz GetCurrentTransactionStartTimestamp(void); |
371 | extern TimestampTz GetCurrentStatementStartTimestamp(void); |
372 | extern TimestampTz GetCurrentTransactionStopTimestamp(void); |
373 | extern void SetCurrentStatementStartTimestamp(void); |
374 | extern int GetCurrentTransactionNestLevel(void); |
375 | extern bool TransactionIdIsCurrentTransactionId(TransactionId xid); |
376 | extern void CommandCounterIncrement(void); |
377 | extern void ForceSyncCommit(void); |
378 | extern void StartTransactionCommand(void); |
379 | extern void SaveTransactionCharacteristics(void); |
380 | extern void RestoreTransactionCharacteristics(void); |
381 | extern void CommitTransactionCommand(void); |
382 | extern void AbortCurrentTransaction(void); |
383 | extern void BeginTransactionBlock(void); |
384 | extern bool EndTransactionBlock(bool chain); |
385 | extern bool PrepareTransactionBlock(const char *gid); |
386 | extern void UserAbortTransactionBlock(bool chain); |
387 | extern void BeginImplicitTransactionBlock(void); |
388 | extern void EndImplicitTransactionBlock(void); |
389 | extern void ReleaseSavepoint(const char *name); |
390 | extern void DefineSavepoint(const char *name); |
391 | extern void RollbackToSavepoint(const char *name); |
392 | extern void BeginInternalSubTransaction(const char *name); |
393 | extern void ReleaseCurrentSubTransaction(void); |
394 | extern void RollbackAndReleaseCurrentSubTransaction(void); |
395 | extern bool IsSubTransaction(void); |
396 | extern Size EstimateTransactionStateSpace(void); |
397 | extern void SerializeTransactionState(Size maxsize, char *start_address); |
398 | extern void StartParallelWorkerTransaction(char *tstatespace); |
399 | extern void EndParallelWorkerTransaction(void); |
400 | extern bool IsTransactionBlock(void); |
401 | extern bool IsTransactionOrTransactionBlock(void); |
402 | extern char TransactionBlockStatusCode(void); |
403 | extern void AbortOutOfAnyTransaction(void); |
404 | extern void PreventInTransactionBlock(bool isTopLevel, const char *stmtType); |
405 | extern void RequireTransactionBlock(bool isTopLevel, const char *stmtType); |
406 | extern void WarnNoTransactionBlock(bool isTopLevel, const char *stmtType); |
407 | extern bool IsInTransactionBlock(bool isTopLevel); |
408 | extern void RegisterXactCallback(XactCallback callback, void *arg); |
409 | extern void UnregisterXactCallback(XactCallback callback, void *arg); |
410 | extern void RegisterSubXactCallback(SubXactCallback callback, void *arg); |
411 | extern void UnregisterSubXactCallback(SubXactCallback callback, void *arg); |
412 | |
413 | extern int xactGetCommittedChildren(TransactionId **ptr); |
414 | |
415 | extern XLogRecPtr XactLogCommitRecord(TimestampTz commit_time, |
416 | int nsubxacts, TransactionId *subxacts, |
417 | int nrels, RelFileNode *rels, |
418 | int nmsgs, SharedInvalidationMessage *msgs, |
419 | bool relcacheInval, bool forceSync, |
420 | int xactflags, |
421 | TransactionId twophase_xid, |
422 | const char *twophase_gid); |
423 | |
424 | extern XLogRecPtr XactLogAbortRecord(TimestampTz abort_time, |
425 | int nsubxacts, TransactionId *subxacts, |
426 | int nrels, RelFileNode *rels, |
427 | int xactflags, TransactionId twophase_xid, |
428 | const char *twophase_gid); |
429 | extern void xact_redo(XLogReaderState *record); |
430 | |
431 | /* xactdesc.c */ |
432 | extern void xact_desc(StringInfo buf, XLogReaderState *record); |
433 | extern const char *xact_identify(uint8 info); |
434 | |
435 | /* also in xactdesc.c, so they can be shared between front/backend code */ |
436 | extern void ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed); |
437 | extern void ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed); |
438 | |
439 | extern void EnterParallelMode(void); |
440 | extern void ExitParallelMode(void); |
441 | extern bool IsInParallelMode(void); |
442 | |
443 | #endif /* XACT_H */ |
444 | |