mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Solve the problem of OID collisions by probing for duplicate OIDs
whenever we generate a new OID. This prevents occasional duplicate-OID errors that can otherwise occur once the OID counter has wrapped around. Duplicate relfilenode values are also checked for when creating new physical files. Per my recent proposal.
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.64 2005/05/19 21:35:45 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.65 2005/08/12 01:35:55 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -247,13 +247,16 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* object id generation support
|
||||
* ----------------------------------------------------------------
|
||||
/*
|
||||
* GetNewObjectId -- allocate a new OID
|
||||
*
|
||||
* OIDs are generated by a cluster-wide counter. Since they are only 32 bits
|
||||
* wide, counter wraparound will occur eventually, and therefore it is unwise
|
||||
* to assume they are unique unless precautions are taken to make them so.
|
||||
* Hence, this routine should generally not be used directly. The only
|
||||
* direct callers should be GetNewOid() and GetNewRelFileNode() in
|
||||
* catalog/catalog.c.
|
||||
*/
|
||||
|
||||
static Oid lastSeenOid = InvalidOid;
|
||||
|
||||
Oid
|
||||
GetNewObjectId(void)
|
||||
{
|
||||
@ -265,8 +268,9 @@ GetNewObjectId(void)
|
||||
* Check for wraparound of the OID counter. We *must* not return 0
|
||||
* (InvalidOid); and as long as we have to check that, it seems a good
|
||||
* idea to skip over everything below FirstNormalObjectId too. (This
|
||||
* basically just reduces the odds of OID collision right after a wrap
|
||||
* occurs.) Note we are relying on unsigned comparison here.
|
||||
* basically just avoids lots of collisions with bootstrap-assigned OIDs
|
||||
* right after a wrap occurs, so as to avoid a possibly large number of
|
||||
* iterations in GetNewOid.) Note we are relying on unsigned comparison.
|
||||
*
|
||||
* During initdb, we start the OID generator at FirstBootstrapObjectId,
|
||||
* so we only enforce wrapping to that point when in bootstrap or
|
||||
@ -310,46 +314,5 @@ GetNewObjectId(void)
|
||||
|
||||
LWLockRelease(OidGenLock);
|
||||
|
||||
lastSeenOid = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
CheckMaxObjectId(Oid assigned_oid)
|
||||
{
|
||||
if (lastSeenOid != InvalidOid && assigned_oid < lastSeenOid)
|
||||
return;
|
||||
|
||||
LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
|
||||
|
||||
if (assigned_oid < ShmemVariableCache->nextOid)
|
||||
{
|
||||
lastSeenOid = ShmemVariableCache->nextOid - 1;
|
||||
LWLockRelease(OidGenLock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we are in the logged oid range, just bump nextOid up */
|
||||
if (assigned_oid <= ShmemVariableCache->nextOid +
|
||||
ShmemVariableCache->oidCount - 1)
|
||||
{
|
||||
ShmemVariableCache->oidCount -=
|
||||
assigned_oid - ShmemVariableCache->nextOid + 1;
|
||||
ShmemVariableCache->nextOid = assigned_oid + 1;
|
||||
LWLockRelease(OidGenLock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have exceeded the logged oid range. We should lock the database
|
||||
* and kill all other backends but we are loading oid's that we can
|
||||
* not guarantee are unique anyway, so we must rely on the user.
|
||||
*/
|
||||
|
||||
XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH);
|
||||
ShmemVariableCache->nextOid = assigned_oid + 1;
|
||||
ShmemVariableCache->oidCount = VAR_OID_PREFETCH - 1;
|
||||
|
||||
LWLockRelease(OidGenLock);
|
||||
}
|
||||
|
Reference in New Issue
Block a user