1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +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:
Tom Lane
2005-08-12 01:36:05 +00:00
parent 9e4a2de844
commit 721e53785d
20 changed files with 416 additions and 268 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.196 2005/08/01 20:31:05 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.197 2005/08/12 01:35:54 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -1069,9 +1069,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
* pointers to one another).
*/
if (!OidIsValid(HeapTupleGetOid(tup)))
HeapTupleSetOid(tup, newoid());
else
CheckMaxObjectId(HeapTupleGetOid(tup));
HeapTupleSetOid(tup, GetNewOid(relation));
}
else
{

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.51 2005/08/02 16:11:57 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.52 2005/08/12 01:35:54 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -1006,6 +1006,15 @@ toast_save_datum(Relation rel, Datum value)
char *data_p;
int32 data_todo;
/*
* Open the toast relation and its index. We can use the index to
* check uniqueness of the OID we assign to the toasted item, even
* though it has additional columns besides OID.
*/
toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock);
toasttupDesc = toastrel->rd_att;
toastidx = index_open(toastrel->rd_rel->reltoastidxid);
/*
* Create the varattrib reference
*/
@@ -1023,7 +1032,8 @@ toast_save_datum(Relation rel, Datum value)
result->va_content.va_external.va_extsize =
VARATT_SIZE(value) - VARHDRSZ;
result->va_content.va_external.va_valueid = newoid();
result->va_content.va_external.va_valueid =
GetNewOidWithIndex(toastrel, toastidx);
result->va_content.va_external.va_toastrelid =
rel->rd_rel->reltoastrelid;
@@ -1043,12 +1053,9 @@ toast_save_datum(Relation rel, Datum value)
data_todo = VARATT_SIZE(value) - VARHDRSZ;
/*
* Open the toast relation. We must explicitly lock the toast index
* because we aren't using an index scan here.
* We must explicitly lock the toast index because we aren't using an
* index scan here.
*/
toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock);
toasttupDesc = toastrel->rd_att;
toastidx = index_open(toastrel->rd_rel->reltoastidxid);
LockRelation(toastidx, RowExclusiveLock);
/*

View File

@@ -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);
}