Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 721e537

Browse files
committed
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.
1 parent 9e4a2de commit 721e537

File tree

20 files changed

+411
-263
lines changed

20 files changed

+411
-263
lines changed

doc/src/sgml/ddl.sgml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.42 2005/07/14 06:17:35 neilc Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.43 2005/08/12 01:35:53 tgl Exp $ -->
22

33
<chapter id="ddl">
44
<title>Data Definition</title>
@@ -871,7 +871,7 @@ CREATE TABLE order_items (
871871
The object identifier (object ID) of a row. This column is only
872872
present if the table was created using <literal>WITH
873873
OIDS</literal>, or if the <xref linkend="guc-default-with-oids">
874-
configuration variable was enabled. This column is of type
874+
configuration variable was set. This column is of type
875875
<type>oid</type> (same name as the column); see <xref
876876
linkend="datatype-oid"> for more information about the type.
877877
</para>
@@ -992,7 +992,13 @@ CREATE TABLE order_items (
992992
<listitem>
993993
<para>
994994
A unique constraint should be created on the OID column of each
995-
table for which the OID will be used to identify rows.
995+
table for which the OID will be used to identify rows. When such
996+
a unique constraint (or unique index) exists, the system takes
997+
care not to generate an OID matching an already-existing row.
998+
(Of course, this is only possible if the table contains fewer
999+
than 2<superscript>32</> (4 billion) rows, and in practice the
1000+
table size had better be much less than that, or performance
1001+
may suffer.)
9961002
</para>
9971003
</listitem>
9981004
<listitem>
@@ -1005,9 +1011,8 @@ CREATE TABLE order_items (
10051011
<listitem>
10061012
<para>
10071013
The tables in question should be created using <literal>WITH
1008-
OIDS</literal> to ensure forward compatibility with future
1009-
releases of <productname>PostgreSQL</productname>. It is
1010-
planned that <literal>WITHOUT OIDS</> will become the default.
1014+
OIDS</literal>. As of <productname>PostgreSQL</productname> 8.1,
1015+
<literal>WITHOUT OIDS</> is the default.
10111016
</para>
10121017
</listitem>
10131018
</itemizedlist>

src/backend/access/heap/heapam.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.196 2005/08/01 20:31:05 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.197 2005/08/12 01:35:54 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1069,9 +1069,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
10691069
* pointers to one another).
10701070
*/
10711071
if (!OidIsValid(HeapTupleGetOid(tup)))
1072-
HeapTupleSetOid(tup, newoid());
1073-
else
1074-
CheckMaxObjectId(HeapTupleGetOid(tup));
1072+
HeapTupleSetOid(tup, GetNewOid(relation));
10751073
}
10761074
else
10771075
{

src/backend/access/heap/tuptoaster.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.51 2005/08/02 16:11:57 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.52 2005/08/12 01:35:54 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1006,6 +1006,15 @@ toast_save_datum(Relation rel, Datum value)
10061006
char *data_p;
10071007
int32 data_todo;
10081008

1009+
/*
1010+
* Open the toast relation and its index. We can use the index to
1011+
* check uniqueness of the OID we assign to the toasted item, even
1012+
* though it has additional columns besides OID.
1013+
*/
1014+
toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock);
1015+
toasttupDesc = toastrel->rd_att;
1016+
toastidx = index_open(toastrel->rd_rel->reltoastidxid);
1017+
10091018
/*
10101019
* Create the varattrib reference
10111020
*/
@@ -1023,7 +1032,8 @@ toast_save_datum(Relation rel, Datum value)
10231032

10241033
result->va_content.va_external.va_extsize =
10251034
VARATT_SIZE(value) - VARHDRSZ;
1026-
result->va_content.va_external.va_valueid = newoid();
1035+
result->va_content.va_external.va_valueid =
1036+
GetNewOidWithIndex(toastrel, toastidx);
10271037
result->va_content.va_external.va_toastrelid =
10281038
rel->rd_rel->reltoastrelid;
10291039

@@ -1043,12 +1053,9 @@ toast_save_datum(Relation rel, Datum value)
10431053
data_todo = VARATT_SIZE(value) - VARHDRSZ;
10441054

10451055
/*
1046-
* Open the toast relation. We must explicitly lock the toast index
1047-
* because we aren't using an index scan here.
1056+
* We must explicitly lock the toast index because we aren't using an
1057+
* index scan here.
10481058
*/
1049-
toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock);
1050-
toasttupDesc = toastrel->rd_att;
1051-
toastidx = index_open(toastrel->rd_rel->reltoastidxid);
10521059
LockRelation(toastidx, RowExclusiveLock);
10531060

10541061
/*

src/backend/access/transam/varsup.c

Lines changed: 13 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
77
*
88
* IDENTIFICATION
9-
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.64 2005/05/19 21:35:45 tgl Exp $
9+
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.65 2005/08/12 01:35:55 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -247,13 +247,16 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
247247
}
248248

249249

250-
/* ----------------------------------------------------------------
251-
* object id generation support
252-
* ----------------------------------------------------------------
250+
/*
251+
* GetNewObjectId -- allocate a new OID
252+
*
253+
* OIDs are generated by a cluster-wide counter. Since they are only 32 bits
254+
* wide, counter wraparound will occur eventually, and therefore it is unwise
255+
* to assume they are unique unless precautions are taken to make them so.
256+
* Hence, this routine should generally not be used directly. The only
257+
* direct callers should be GetNewOid() and GetNewRelFileNode() in
258+
* catalog/catalog.c.
253259
*/
254-
255-
static Oid lastSeenOid = InvalidOid;
256-
257260
Oid
258261
GetNewObjectId(void)
259262
{
@@ -265,8 +268,9 @@ GetNewObjectId(void)
265268
* Check for wraparound of the OID counter. We *must* not return 0
266269
* (InvalidOid); and as long as we have to check that, it seems a good
267270
* idea to skip over everything below FirstNormalObjectId too. (This
268-
* basically just reduces the odds of OID collision right after a wrap
269-
* occurs.) Note we are relying on unsigned comparison here.
271+
* basically just avoids lots of collisions with bootstrap-assigned OIDs
272+
* right after a wrap occurs, so as to avoid a possibly large number of
273+
* iterations in GetNewOid.) Note we are relying on unsigned comparison.
270274
*
271275
* During initdb, we start the OID generator at FirstBootstrapObjectId,
272276
* so we only enforce wrapping to that point when in bootstrap or
@@ -310,46 +314,5 @@ GetNewObjectId(void)
310314

311315
LWLockRelease(OidGenLock);
312316

313-
lastSeenOid = result;
314-
315317
return result;
316318
}
317-
318-
void
319-
CheckMaxObjectId(Oid assigned_oid)
320-
{
321-
if (lastSeenOid != InvalidOid && assigned_oid < lastSeenOid)
322-
return;
323-
324-
LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
325-
326-
if (assigned_oid < ShmemVariableCache->nextOid)
327-
{
328-
lastSeenOid = ShmemVariableCache->nextOid - 1;
329-
LWLockRelease(OidGenLock);
330-
return;
331-
}
332-
333-
/* If we are in the logged oid range, just bump nextOid up */
334-
if (assigned_oid <= ShmemVariableCache->nextOid +
335-
ShmemVariableCache->oidCount - 1)
336-
{
337-
ShmemVariableCache->oidCount -=
338-
assigned_oid - ShmemVariableCache->nextOid + 1;
339-
ShmemVariableCache->nextOid = assigned_oid + 1;
340-
LWLockRelease(OidGenLock);
341-
return;
342-
}
343-
344-
/*
345-
* We have exceeded the logged oid range. We should lock the database
346-
* and kill all other backends but we are loading oid's that we can
347-
* not guarantee are unique anyway, so we must rely on the user.
348-
*/
349-
350-
XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH);
351-
ShmemVariableCache->nextOid = assigned_oid + 1;
352-
ShmemVariableCache->oidCount = VAR_OID_PREFETCH - 1;
353-
354-
LWLockRelease(OidGenLock);
355-
}

0 commit comments

Comments
 (0)