/* *Workerssynchronizetransactionstateatthebeginningofeachparallel *operation,sowecan'taccountfornewXIDsafterthatpoint.
*/ if (IsInParallelMode())
elog(ERROR, "cannot assign TransactionIds during a parallel operation");
/* safety check, we should never get this far in a HS standby */ if (RecoveryInProgress())
elog(ERROR, "cannot assign TransactionIds during recovery");
if (IsUnderPostmaster &&
TransactionIdFollowsOrEquals(xid, xidStopLimit))
{ char *oldest_datname = get_database_name(oldest_datoid);
/* complain even if that DB has disappeared */ if (oldest_datname)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database \"%s\"",
oldest_datname),
errhint("Execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots."))); else
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database with OID %u",
oldest_datoid),
errhint("Execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
} elseif (TransactionIdFollowsOrEquals(xid, xidWarnLimit))
{ char *oldest_datname = get_database_name(oldest_datoid);
/* complain even if that DB has disappeared */ if (oldest_datname)
ereport(WARNING,
(errmsg("database \"%s\" must be vacuumed within %u transactions",
oldest_datname,
xidWrapLimit - xid),
errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots."))); else
ereport(WARNING,
(errmsg("database with OID %u must be vacuumed within %u transactions",
oldest_datoid,
xidWrapLimit - xid),
errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
}
/* Re-acquire lock and start over */
LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
full_xid = TransamVariables->nextXid;
xid = XidFromFullTransactionId(full_xid);
}
/* Fast return if this isn't an xid high enough to move the needle. */
next_xid = XidFromFullTransactionId(TransamVariables->nextXid); if (!TransactionIdFollowsOrEquals(xid, next_xid)) return;
/* Grab lock for just long enough to set the new limit values */
LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
TransamVariables->oldestXid = oldest_datfrozenxid;
TransamVariables->xidVacLimit = xidVacLimit;
TransamVariables->xidWarnLimit = xidWarnLimit;
TransamVariables->xidStopLimit = xidStopLimit;
TransamVariables->xidWrapLimit = xidWrapLimit;
TransamVariables->oldestXidDB = oldest_datoid;
curXid = XidFromFullTransactionId(TransamVariables->nextXid);
LWLockRelease(XidGenLock);
/* Log the info */
ereport(DEBUG1,
(errmsg_internal("transaction ID wrap limit is %u, limited by database with OID %u",
xidWrapLimit, oldest_datoid)));
/* Give an immediate warning if past the wrap warn point */ if (TransactionIdFollowsOrEquals(curXid, xidWarnLimit) && !InRecovery)
{ char *oldest_datname;
if (oldest_datname)
ereport(WARNING,
(errmsg("database \"%s\" must be vacuumed within %u transactions",
oldest_datname,
xidWrapLimit - curXid),
errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots."))); else
ereport(WARNING,
(errmsg("database with OID %u must be vacuumed within %u transactions",
oldest_datoid,
xidWrapLimit - curXid),
errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
}
}
/* Locking is probably not really necessary, but let's be careful */
LWLockAcquire(XidGenLock, LW_SHARED);
nextXid = XidFromFullTransactionId(TransamVariables->nextXid);
xidVacLimit = TransamVariables->xidVacLimit;
oldestXid = TransamVariables->oldestXid;
oldestXidDB = TransamVariables->oldestXidDB;
LWLockRelease(XidGenLock);
if (!TransactionIdIsNormal(oldestXid)) returntrue; /* shouldn't happen, but just in case */ if (!TransactionIdIsValid(xidVacLimit)) returntrue; /* this shouldn't happen anymore either */ if (TransactionIdFollowsOrEquals(nextXid, xidVacLimit)) returntrue; /* past xidVacLimit, don't delay updating */ if (!SearchSysCacheExists1(DATABASEOID, ObjectIdGetDatum(oldestXidDB))) returntrue; /* could happen, per comments above */ returnfalse;
}
/* *GetNewObjectId--allocateanewOID * *OIDsaregeneratedbyacluster-widecounter.Sincetheyareonly32bits *wide,counterwraparoundwilloccureventually,andthereforeitisunwise *toassumetheyareuniqueunlessprecautionsaretakentomakethemso. *Hence,thisroutineshouldgenerallynotbeuseddirectly.Theonlydirect *callersshouldbeGetNewOidWithIndex()andGetNewRelFileNumber()in *catalog/catalog.c.
*/
Oid
GetNewObjectId(void)
{
Oid result;
/* safety check, we should never get this far in a HS standby */ if (RecoveryInProgress())
elog(ERROR, "cannot assign OIDs during recovery");
LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
/* *CheckforwraparoundoftheOIDcounter.We*must*notreturn0 *(InvalidOid),andinnormaloperationwemustn'treturnanythingbelow *FirstNormalObjectIdsincethatrangeisreservedforinitdb(see *IsCatalogRelationOid()).Notewearerelyingonunsignedcomparison. * *Duringinitdb,westarttheOIDgeneratoratFirstGenbkiObjectId,sowe *onlywrapifbeforethatpointwheninbootstraporstandalonemode. *Thefirsttimethroughthisroutineafternormalpostmasterstart,the *counterwillbeforceduptoFirstNormalObjectId.Thismechanism *leavestheOIDsbetweenFirstGenbkiObjectIdandFirstNormalObjectId *availableforautomaticassignmentduringinitdb,whileensuringthey *willneverconflictwithuser-assignedOIDs.
*/ if (TransamVariables->nextOid < ((Oid) FirstNormalObjectId))
{ if (IsPostmasterEnvironment)
{ /* wraparound, or first post-initdb assignment, in normal mode */
TransamVariables->nextOid = FirstNormalObjectId;
TransamVariables->oidCount = 0;
} else
{ /* we may be bootstrapping, so don't enforce the full range */ if (TransamVariables->nextOid < ((Oid) FirstGenbkiObjectId))
{ /* wraparound in standalone mode (unlikely but possible) */
TransamVariables->nextOid = FirstNormalObjectId;
TransamVariables->oidCount = 0;
}
}
}
/* If we run out of logged for use oids then we must log more */ if (TransamVariables->oidCount == 0)
{
XLogPutNextOid(TransamVariables->nextOid + VAR_OID_PREFETCH);
TransamVariables->oidCount = VAR_OID_PREFETCH;
}
/* *SetNextObjectId * *Thismayonlybecalledduringinitdb;itadvancestheOIDcounter *tothespecifiedvalue.
*/ staticvoid
SetNextObjectId(Oid nextOid)
{ /* Safety check, this is only allowable during initdb */ if (IsPostmasterEnvironment)
elog(ERROR, "cannot advance OID counter anymore");
/* Taking the lock is, therefore, just pro forma; but do it anyway */
LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
if (TransamVariables->nextOid > nextOid)
elog(ERROR, "too late to advance OID counter to %u, it is now %u",
nextOid, TransamVariables->nextOid);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.