diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/twophase.c | 40 | ||||
-rw-r--r-- | src/backend/access/transam/xact.c | 184 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 25 | ||||
-rw-r--r-- | src/include/access/twophase.h | 6 | ||||
-rw-r--r-- | src/include/access/xact.h | 6 |
5 files changed, 112 insertions, 149 deletions
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 43c8732245..749375e3fd 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -861,13 +861,8 @@ StartPrepare(GlobalTransaction gxact) * * Calculates CRC and writes state file to WAL and in pg_twophase directory. */ -#ifdef PGXC -void -EndPrepare(GlobalTransaction gxact, bool write_2pc_file) -#else void EndPrepare(GlobalTransaction gxact) -#endif { TransactionId xid = gxact->proc.xid; TwoPhaseFileHeader *hdr; @@ -904,11 +899,6 @@ EndPrepare(GlobalTransaction gxact) * PANIC anyway. */ -#ifdef PGXC - /* Write 2PC state file on Coordinator side if a DDL is involved in transaction */ - if (write_2pc_file) - { -#endif TwoPhaseFilePath(path, xid); fd = BasicOpenFile(path, @@ -981,9 +971,6 @@ EndPrepare(GlobalTransaction gxact) * We save the PREPARE record's location in the gxact for later use by * CheckPointTwoPhase. */ -#ifdef PGXC - } -#endif START_CRIT_SECTION(); @@ -995,15 +982,6 @@ EndPrepare(GlobalTransaction gxact) /* If we crash now, we have prepared: WAL replay will fix things */ -#ifdef PGXC - /* - * Just write 2PC state file on Datanodes - * or on Coordinators if DDL queries are involved. - */ - if (write_2pc_file) - { -#endif - /* write correct CRC and close file */ if ((write(fd, &statefile_crc, sizeof(pg_crc32))) != sizeof(pg_crc32)) { @@ -1018,10 +996,6 @@ EndPrepare(GlobalTransaction gxact) (errcode_for_file_access(), errmsg("could not close two-phase state file: %m"))); -#ifdef PGXC - } -#endif - /* * Mark the prepared transaction as valid. As soon as xact.c marks MyProc * as not running our XID (which it will do immediately after this @@ -1872,17 +1846,3 @@ RecordTransactionAbortPrepared(TransactionId xid, END_CRIT_SECTION(); } - - -#ifdef PGXC -/* - * Remove a gxact on a Coordinator, - * this is used to be able to prepare a commit transaction on another coordinator than the one - * who prepared the transaction, for a transaction that does not include DDLs - */ -void -RemoveGXactCoord(GlobalTransaction gxact) -{ - RemoveGXact(gxact); -} -#endif diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index ea1215d45c..e033d4f4f8 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -112,14 +112,13 @@ typedef enum TBlockState TBLOCK_BEGIN, /* starting transaction block */ TBLOCK_INPROGRESS, /* live transaction */ TBLOCK_END, /* COMMIT received */ +#ifdef PGXC + TBLOCK_END_NOT_GTM, /* COMMIT received but do not commit on GTM */ +#endif TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */ TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */ TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */ TBLOCK_PREPARE, /* live xact, PREPARE received */ -#ifdef PGXC - TBLOCK_PREPARE_NO_2PC_FILE, /* PREPARE receive but skip 2PC file creation - * and Commit gxact */ -#endif /* subtransaction states */ TBLOCK_SUBBEGIN, /* starting a subtransaction */ TBLOCK_SUBINPROGRESS, /* live subtransaction */ @@ -287,7 +286,7 @@ static void CallSubXactCallbacks(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid); static void CleanupTransaction(void); -static void CommitTransaction(void); +static void CommitTransaction(bool contact_gtm); static TransactionId RecordTransactionAbort(bool isSubXact); static void StartTransaction(void); @@ -312,7 +311,7 @@ static const char *TransStateAsString(TransState state); #ifdef PGXC /* PGXC_COORD */ static GlobalTransactionId GetGlobalTransactionId(TransactionState s); -static void PrepareTransaction(bool write_2pc_file, bool is_implicit); +static void PrepareTransaction(bool is_implicit); /* ---------------------------------------------------------------- * PG-XC Functions @@ -1744,7 +1743,7 @@ StartTransaction(void) * NB: if you change this routine, better look at PrepareTransaction too! */ static void -CommitTransaction(void) +CommitTransaction(bool contact_gtm) { TransactionState s = CurrentTransactionState; TransactionId latestXid; @@ -1754,7 +1753,7 @@ CommitTransaction(void) char implicitgid[256]; TransactionId xid = GetCurrentTransactionId(); - if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && contact_gtm) PreparePGXCNodes = PGXCNodeIsImplicit2PC(&PrepareLocalCoord); if (PrepareLocalCoord || PreparePGXCNodes) @@ -1768,7 +1767,7 @@ CommitTransaction(void) * If current transaction has a DDL, and involves more than 1 Coordinator, * PREPARE first on local Coordinator. */ - PrepareTransaction(true, true); + PrepareTransaction(true); } else { @@ -1865,7 +1864,7 @@ CommitTransaction(void) * * This is called only if it is not necessary to prepare the nodes. */ - if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !PreparePGXCNodes) + if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !PreparePGXCNodes && contact_gtm) PGXCNodeCommit(); #endif @@ -1892,12 +1891,12 @@ CommitTransaction(void) * * Also do not commit a transaction that has already been prepared on Datanodes */ - if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !PreparePGXCNodes) + if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !PreparePGXCNodes && contact_gtm) { CommitTranGTM(s->globalTransactionId); latestXid = s->globalTransactionId; } - else if (IS_PGXC_DATANODE || IsConnFromCoord()) + else if ((IS_PGXC_DATANODE || IsConnFromCoord()) && contact_gtm) { /* If we are autovacuum, commit on GTM */ if ((IsAutoVacuumWorkerProcess() || GetForceXidFromGTM()) @@ -2086,7 +2085,7 @@ CommitTransaction(void) * this is made by CommitTransaction when transaction has been committed on Nodes. */ static void -PrepareTransaction(bool write_2pc_file, bool is_implicit) +PrepareTransaction(bool is_implicit) #else static void PrepareTransaction(void) @@ -2221,7 +2220,7 @@ PrepareTransaction(void) * updates, because the transaction manager might get confused if we lose * a global transaction. */ - EndPrepare(gxact, write_2pc_file); + EndPrepare(gxact); /* * Now we clean up backend-internal state and release internal resources. @@ -2272,17 +2271,6 @@ PrepareTransaction(void) #ifdef PGXC /* - * We want to be able to commit a prepared transaction from another coordinator, - * so clean up the gxact in shared memory also. - */ - if (!write_2pc_file) - { - RemoveGXactCoord(gxact); - } -#endif - -#ifdef PGXC - /* * In case of an implicit 2PC, ressources are released by CommitTransaction() */ if (!is_implicit) @@ -2661,6 +2649,9 @@ StartTransactionCommand(void) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: @@ -2669,9 +2660,6 @@ StartTransactionCommand(void) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(ERROR, "StartTransactionCommand: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -2710,7 +2698,11 @@ CommitTransactionCommand(void) * transaction commit, and return to the idle state. */ case TBLOCK_STARTED: +#ifdef PGXC + CommitTransaction(true); +#else CommitTransaction(); +#endif s->blockState = TBLOCK_DEFAULT; break; @@ -2739,10 +2731,20 @@ CommitTransactionCommand(void) * idle state. */ case TBLOCK_END: +#ifdef PGXC + CommitTransaction(true); +#else CommitTransaction(); +#endif s->blockState = TBLOCK_DEFAULT; break; +#ifdef PGXC + case TBLOCK_END_NOT_GTM: + CommitTransaction(false); + s->blockState = TBLOCK_DEFAULT; + break; +#endif /* * Here we are in the middle of a transaction block but one of the * commands caused an abort so we do nothing but remain in the @@ -2778,20 +2780,13 @@ CommitTransactionCommand(void) * return to the idle state. */ case TBLOCK_PREPARE: - PrepareTransaction(true, false); - s->blockState = TBLOCK_DEFAULT; - break; - #ifdef PGXC - /* - * We are complieting a PREPARE TRANSACTION for a pgxc transaction - * that involved DDLs on a Coordinator. - */ - case TBLOCK_PREPARE_NO_2PC_FILE: - PrepareTransaction(false, false); + PrepareTransaction(false); +#else + PrepareTransaction(); +#endif s->blockState = TBLOCK_DEFAULT; break; -#endif /* * We were just issued a SAVEPOINT inside a transaction block. @@ -2820,23 +2815,21 @@ CommitTransactionCommand(void) if (s->blockState == TBLOCK_END) { Assert(s->parent == NULL); +#ifdef PGXC + CommitTransaction(true); +#else CommitTransaction(); +#endif s->blockState = TBLOCK_DEFAULT; } else if (s->blockState == TBLOCK_PREPARE) { Assert(s->parent == NULL); - PrepareTransaction(true, false); - s->blockState = TBLOCK_DEFAULT; - } #ifdef PGXC - else if (s->blockState == TBLOCK_PREPARE_NO_2PC_FILE) - { - Assert(s->parent == NULL); - PrepareTransaction(false, false); + PrepareTransaction(false); +#endif s->blockState = TBLOCK_DEFAULT; } -#endif else { Assert(s->blockState == TBLOCK_INPROGRESS || @@ -2994,6 +2987,9 @@ AbortCurrentTransaction(void) * the transaction). */ case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; @@ -3034,9 +3030,6 @@ AbortCurrentTransaction(void) * the transaction). */ case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; @@ -3380,6 +3373,9 @@ BeginTransactionBlock(void) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: @@ -3388,9 +3384,6 @@ BeginTransactionBlock(void) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "BeginTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3409,19 +3402,18 @@ BeginTransactionBlock(void) * We do it this way because it's not convenient to change memory context, * resource owner, etc while executing inside a Portal. */ -#ifdef PGXC -bool -PrepareTransactionBlock(char *gid, bool write_2pc_file) -#else bool PrepareTransactionBlock(char *gid) -#endif { TransactionState s; bool result; /* Set up to commit the current transaction */ +#ifdef PGXC + result = EndTransactionBlock(true); +#else result = EndTransactionBlock(); +#endif /* If successful, change outer tblock state to PREPARE */ if (result) @@ -3436,16 +3428,6 @@ PrepareTransactionBlock(char *gid) /* Save GID where PrepareTransaction can find it again */ prepareGID = MemoryContextStrdup(TopTransactionContext, gid); -#ifdef PGXC - /* - * For a Postgres-XC Coordinator, prepare is done for a transaction - * if and only if a DDL was involved in the transaction. - * If not, it is enough to prepare it on Datanodes involved only. - */ - if (!write_2pc_file) - s->blockState = TBLOCK_PREPARE_NO_2PC_FILE; - else -#endif s->blockState = TBLOCK_PREPARE; } else @@ -3476,7 +3458,11 @@ PrepareTransactionBlock(char *gid) * resource owner, etc while executing inside a Portal. */ bool +#ifdef PGXC +EndTransactionBlock(bool contact_gtm) +#else EndTransactionBlock(void) +#endif { TransactionState s = CurrentTransactionState; bool result = false; @@ -3488,6 +3474,11 @@ EndTransactionBlock(void) * to COMMIT. */ case TBLOCK_INPROGRESS: +#ifdef PGXC + if (!contact_gtm) + s->blockState = TBLOCK_END_NOT_GTM; + else +#endif s->blockState = TBLOCK_END; result = true; break; @@ -3566,6 +3557,9 @@ EndTransactionBlock(void) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: @@ -3574,9 +3568,6 @@ EndTransactionBlock(void) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3661,6 +3652,9 @@ UserAbortTransactionBlock(void) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: @@ -3669,9 +3663,6 @@ UserAbortTransactionBlock(void) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "UserAbortTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3709,6 +3700,9 @@ DefineSavepoint(char *name) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT: case TBLOCK_SUBABORT: @@ -3719,9 +3713,6 @@ DefineSavepoint(char *name) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "DefineSavepoint: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3768,6 +3759,9 @@ ReleaseSavepoint(List *options) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT: case TBLOCK_SUBABORT: @@ -3778,9 +3772,6 @@ ReleaseSavepoint(List *options) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "ReleaseSavepoint: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3871,6 +3862,9 @@ RollbackToSavepoint(List *options) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: @@ -3879,9 +3873,6 @@ RollbackToSavepoint(List *options) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "RollbackToSavepoint: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3964,10 +3955,10 @@ BeginInternalSubTransaction(char *name) case TBLOCK_STARTED: case TBLOCK_INPROGRESS: case TBLOCK_END: - case TBLOCK_PREPARE: #ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: + case TBLOCK_END_NOT_GTM: #endif + case TBLOCK_PREPARE: case TBLOCK_SUBINPROGRESS: /* Normal subtransaction start */ PushTransaction(); @@ -3980,7 +3971,6 @@ BeginInternalSubTransaction(char *name) if (name) s->name = MemoryContextStrdup(TopTransactionContext, name); break; - /* These cases are invalid. */ case TBLOCK_DEFAULT: case TBLOCK_BEGIN: @@ -4051,6 +4041,9 @@ RollbackAndReleaseCurrentSubTransaction(void) case TBLOCK_SUBBEGIN: case TBLOCK_INPROGRESS: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT: case TBLOCK_ABORT_END: @@ -4060,9 +4053,6 @@ RollbackAndReleaseCurrentSubTransaction(void) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -4109,11 +4099,11 @@ AbortOutOfAnyTransaction(void) case TBLOCK_BEGIN: case TBLOCK_INPROGRESS: case TBLOCK_END: - case TBLOCK_ABORT_PENDING: - case TBLOCK_PREPARE: #ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: + case TBLOCK_END_NOT_GTM: #endif + case TBLOCK_ABORT_PENDING: + case TBLOCK_PREPARE: /* In a transaction, so clean up */ AbortTransaction(); CleanupTransaction(); @@ -4203,11 +4193,11 @@ TransactionBlockStatusCode(void) case TBLOCK_INPROGRESS: case TBLOCK_SUBINPROGRESS: case TBLOCK_END: - case TBLOCK_SUBEND: - case TBLOCK_PREPARE: #ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: + case TBLOCK_END_NOT_GTM: #endif + case TBLOCK_SUBEND: + case TBLOCK_PREPARE: return 'T'; /* in transaction */ case TBLOCK_ABORT: case TBLOCK_SUBABORT: @@ -4703,10 +4693,10 @@ BlockStateAsString(TBlockState blockState) return "ABORT END"; case TBLOCK_ABORT_PENDING: return "ABORT PEND"; + case TBLOCK_PREPARE: #ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: + case TBLOCK_END_NOT_GTM: #endif - case TBLOCK_PREPARE: return "PREPARE"; case TBLOCK_SUBBEGIN: return "SUB BEGIN"; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 9dcc634606..1be891e0c6 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -316,7 +316,11 @@ ProcessUtility(Node *parsetree, break; case TRANS_STMT_COMMIT: +#ifdef PGXC + if (!EndTransactionBlock(true)) +#else if (!EndTransactionBlock()) +#endif { /* report unsuccessful commit in completionTag */ if (completionTag) @@ -342,16 +346,31 @@ ProcessUtility(Node *parsetree, if (IsConnFromCoord()) operation_local = true; - if (!PrepareTransactionBlock(stmt->gid, operation_local)) + if (operation_local) { -#else +#endif if (!PrepareTransactionBlock(stmt->gid)) { -#endif /* report unsuccessful commit in completionTag */ if (completionTag) strcpy(completionTag, "ROLLBACK"); } +#ifdef PGXC + } + else + { + /* + * In this case commit locally to erase the transaction traces + * but do not contact GTM + */ + if (!EndTransactionBlock(false)) + { + /* report unsuccessful commit in completionTag */ + if (completionTag) + strcpy(completionTag, "ROLLBACK"); + } + } +#endif break; case TRANS_STMT_COMMIT_PREPARED: diff --git a/src/include/access/twophase.h b/src/include/access/twophase.h index 58bc7e4d43..8261ee7620 100644 --- a/src/include/access/twophase.h +++ b/src/include/access/twophase.h @@ -36,13 +36,7 @@ extern GlobalTransaction MarkAsPreparing(TransactionId xid, const char *gid, TimestampTz prepared_at, Oid owner, Oid databaseid); -#ifdef PGXC -extern void RemoveGXactCoord(GlobalTransaction gxact); -extern void EndPrepare(GlobalTransaction gxact, bool write_2pc_file); -#else extern void EndPrepare(GlobalTransaction gxact); -#endif - extern void StartPrepare(GlobalTransaction gxact); extern TransactionId PrescanPreparedTransactions(void); diff --git a/src/include/access/xact.h b/src/include/access/xact.h index d211329bd3..6ff489ff7d 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -172,12 +172,12 @@ extern void AbortCurrentTransactionOnce(void); #endif extern void AbortCurrentTransaction(void); extern void BeginTransactionBlock(void); -extern bool EndTransactionBlock(void); #ifdef PGXC -extern bool PrepareTransactionBlock(char *gid, bool write_2pc_file); +extern bool EndTransactionBlock(bool contact_gtm); #else -extern bool PrepareTransactionBlock(char *gid); +extern bool EndTransactionBlock(void); #endif +extern bool PrepareTransactionBlock(char *gid); extern void UserAbortTransactionBlock(void); extern void ReleaseSavepoint(List *options); extern void DefineSavepoint(char *name); |