| 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 | |