diff options
| author | Pavan Deolasee | 2014-12-05 11:42:16 +0000 |
|---|---|---|
| committer | Pavan Deolasee | 2015-04-15 05:46:40 +0000 |
| commit | fc9ad1988de90a3aaf3c9bda0033df9cec26bd24 (patch) | |
| tree | 37c5c98ccbf0e918bfa68ae526a9baa5d199bae3 /src | |
| parent | f343fcd843511ae694657970d99d6dbca5f37799 (diff) | |
Refactor the XID assignment code.
The current code had become quite messy and error-prone. So that has been
refactored. We now make some simple assumptions to allow a gloabl XID to be
fetched from the GTM directly or use of local XIDs. Tha latter is restricted
only for initdb while former is useful for autovacuum launcher/worker, backend
initializing and certain commands such as VACUUM/CLUSTER which can't be run
inside a transaction block
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/access/transam/varsup.c | 139 |
1 files changed, 45 insertions, 94 deletions
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index 5fe2369344..9ec73a755f 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -149,17 +149,36 @@ GetNewTransactionId(bool isSubXact) /* Initialize transaction ID */ xid = InvalidTransactionId; - if ((IS_PGXC_COORDINATOR && !IsConnFromCoord()) || IsPGXCNodeXactDatanodeDirect()) + /* + * Get XID from GTM before acquiring the lock as concurrent connections are + * being handled on GTM side even if the lock is acquired in a different + * order. + * + * PGXC sessions should typically use gloabl XID passed down by + * coordinators (or datanodes in case of datanode-datanode connections). + * But we make following exceptions: + * + * 1. If this is a coordinator to which client has connected + * (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + * + * 2. If we are autovacuum launcher or worker process + * 3. We have been explicitly told to get an XID from the GTM, because + * certain commands such as VACUUM and CLUSTER cannot be run inside a + * transaction block + * 4. Or we start currently starting up a new backend which requires a + * valid XID/snapshot for catalog access + * + */ + if ((IS_PGXC_COORDINATOR && !IsConnFromCoord()) || + IsAutoVacuumWorkerProcess() || + IsAutoVacuumLauncherProcess() || + GetForceXidFromGTM() || + (IsInitProcessingMode() && IsPostmasterEnvironment)) { - /* - * Get XID from GTM before acquiring the lock as concurrent connections are - * being handled on GTM side even if the lock is acquired in a different - * order. - */ - if (IsAutoVacuumWorkerProcess() && (MyPgXact->vacuumFlags & PROC_IN_VACUUM)) - xid = (TransactionId) BeginTranAutovacuumGTM(); + if (MyPgXact->vacuumFlags & PROC_IN_VACUUM) + next_xid = xid = (TransactionId) BeginTranAutovacuumGTM(); else - xid = (TransactionId) BeginTranGTM(timestamp); + next_xid = xid = (TransactionId) BeginTranGTM(timestamp); *timestamp_received = true; } #endif /* PGXC */ @@ -167,98 +186,30 @@ GetNewTransactionId(bool isSubXact) LWLockAcquire(XidGenLock, LW_EXCLUSIVE); #ifdef PGXC - /* Only remote Coordinator or a Datanode accessed directly by an application can get a GXID */ - if ((IS_PGXC_COORDINATOR && !IsConnFromCoord()) || IsPGXCNodeXactDatanodeDirect()) + /* + * Unless we are running initdb (which sets useLocalXid to true), we must + * have either got a valid global XID, either from the coordinator/datanode + * or fetched directly from the GTM. Everything else warrants an error + */ + if (!useLocalXid) { - if (TransactionIdIsValid(xid)) - { - /* Log some information about the new transaction ID obtained */ - if (IsAutoVacuumWorkerProcess() && (MyPgXact->vacuumFlags & PROC_IN_VACUUM)) - elog(DEBUG1, "Assigned new transaction ID from GTM for autovacuum = %d", xid); - else - elog(DEBUG1, "Assigned new transaction ID from GTM = %d", xid); - - if (!TransactionIdFollowsOrEquals(xid, ShmemVariableCache->nextXid)) - { - increment_xid = false; - ereport(DEBUG1, - (errmsg("xid (%d) was less than ShmemVariableCache->nextXid (%d)", - xid, ShmemVariableCache->nextXid))); - } - else - ShmemVariableCache->nextXid = xid; - } - else - { - ereport(WARNING, - (errmsg("Xid is invalid."))); - - /* Problem is already reported, so just remove lock and return */ - LWLockRelease(XidGenLock); - return xid; - } - } - else if(IS_PGXC_DATANODE || IsConnFromCoord()) - { -#ifdef XCP - /* - * (IS_PGXC_DATANODE && IsInitProcessingMode() && IsPostmasterEnvironment) - * handles new connections, ensures XID is consumed then, but not during initdb - */ - if (IsAutoVacuumWorkerProcess() || IsAutoVacuumLauncherProcess() || (IS_PGXC_DATANODE && IsInitProcessingMode() && IsPostmasterEnvironment)) -#else - if (IsAutoVacuumWorkerProcess()) -#endif - { - /* - * For an autovacuum worker process, get transaction ID directly from GTM. - * If this vacuum process is a vacuum analyze, its GXID has to be excluded - * from snapshots so use a special function for this purpose. - * For a simple worker get transaction ID like a normal transaction would do. - */ - if (MyPgXact->vacuumFlags & PROC_IN_VACUUM) - next_xid = (TransactionId) BeginTranAutovacuumGTM(); - else - next_xid = (TransactionId) BeginTranGTM(timestamp); - } - else if (GetForceXidFromGTM()) - { - elog (DEBUG1, "Force get XID from GTM"); - /* try and get gxid directly from GTM */ - next_xid = (TransactionId) BeginTranGTM(NULL); - } - if (TransactionIdIsValid(next_xid)) { xid = next_xid; - elog(DEBUG1, "TransactionId = %d", next_xid); - next_xid = InvalidTransactionId; /* reset */ - if (!TransactionIdFollowsOrEquals(xid, ShmemVariableCache->nextXid)) - { - /* This should be ok, due to concurrency from multiple coords - * passing down the xids. - * We later do not want to bother incrementing the value - * in shared memory though. - */ - increment_xid = false; - elog(DEBUG1, "xid (%d) does not follow ShmemVariableCache->nextXid (%d)", - xid, ShmemVariableCache->nextXid); - } - else + next_xid = InvalidTransactionId; + if (TransactionIdFollowsOrEquals(xid, ShmemVariableCache->nextXid)) ShmemVariableCache->nextXid = xid; - } - else - { - if (IsConnFromCoord()) - { - elog(ERROR, "Coordinator has not provided xid for the command"); - } - /* Fallback to default, needed for initdb */ - elog(LOG, "Falling back to local Xid. Was = %d, now is = %d. autovacLaunch = %d", - next_xid, ShmemVariableCache->nextXid, IsAutoVacuumLauncherProcess()); - xid = ShmemVariableCache->nextXid; } + else + ereport(ERROR, + (errcode(ERRCODE_SYSTEM_ERROR), + errmsg("GTM generated global XID not available"), + errhint("Check if GTM/GTM-proxy is running @ %s:%d and " + "reachable from this host. Your firewall could also " + "block access to a host/port", GtmHost, GtmPort))); } + else + xid = ShmemVariableCache->nextXid; #else xid = ShmemVariableCache->nextXid; #endif /* PGXC */ |
