Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita49d081

Browse files
committed
Replace explicit PIN entries in pg_depend with an OID range test.
As of v14, pg_depend contains almost 7000 "pin" entries recordingthe OIDs of built-in objects. This is a fair amount of bloat forevery database, and it adds time to pg_depend lookups as well asinitdb. We can get rid of all of those entries in favor of an OIDrange check, i.e. "OIDs below FirstUnpinnedObjectId are pinned".(template1 and the public schema are exceptions. Those exceptionsare now wired into IsPinnedObject() instead of initdb's code forfilling pg_depend, but it's the same amount of cruft either way.)The contents of pg_shdepend are modified likewise.Discussion:https://postgr.es/m/3737988.1618451008@sss.pgh.pa.us
1 parente529b2d commita49d081

File tree

25 files changed

+291
-433
lines changed

25 files changed

+291
-433
lines changed

‎doc/src/sgml/bki.sgml

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -418,19 +418,33 @@
418418
<para>
419419
If <filename>genbki.pl</filename> needs to assign an OID to a catalog
420420
entry that does not have a manually-assigned OID, it will use a value in
421-
the range 10000&mdash;11999. The server's OID counter is set to 12000
422-
at the start of a bootstrap run. Thus objects created by regular SQL
423-
commands during the later phases of bootstrap, such as objects created
424-
while running the <filename>information_schema.sql</filename> script,
425-
receive OIDs of 12000 or above.
421+
the range 10000&mdash;11999. The server's OID counter is set to 10000
422+
at the start of a bootstrap run, so that any objects created on-the-fly
423+
during bootstrap processing also receive OIDs in this range. (The
424+
usual OID assignment mechanism takes care of preventing any conflicts.)
425+
</para>
426+
427+
<para>
428+
Objects with OIDs below <symbol>FirstUnpinnedObjectId</symbol> (12000)
429+
are considered <quote>pinned</quote>, preventing them from being
430+
deleted. (There are a small number of exceptions, which are
431+
hard-wired into <function>IsPinnedObject()</function>.)
432+
<application>initdb</application> forces the OID counter up
433+
to <symbol>FirstUnpinnedObjectId</symbol> as soon as it's ready to
434+
create unpinned objects. Thus objects created during the later phases
435+
of <application>initdb</application>, such as objects created while
436+
running the <filename>information_schema.sql</filename> script, will
437+
not be pinned, while all objects known
438+
to <filename>genbki.pl</filename> will be.
426439
</para>
427440

428441
<para>
429442
OIDs assigned during normal database operation are constrained to be
430443
16384 or higher. This ensures that the range 10000&mdash;16383 is free
431444
for OIDs assigned automatically by <filename>genbki.pl</filename> or
432-
during bootstrap. These automatically-assigned OIDs are not considered
433-
stable, and may change from one installation to another.
445+
during <application>initdb</application>. These
446+
automatically-assigned OIDs are not considered stable, and may change
447+
from one installation to another.
434448
</para>
435449
</sect2>
436450

‎doc/src/sgml/catalogs.sgml

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3264,8 +3264,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
32643264
(references <link linkend="catalog-pg-class"><structname>pg_class</structname></link>.<structfield>oid</structfield>)
32653265
</para>
32663266
<para>
3267-
The OID of the system catalog the dependent object is in,
3268-
or zero for a <symbol>DEPENDENCY_PIN</symbol> entry
3267+
The OID of the system catalog the dependent object is in
32693268
</para></entry>
32703269
</row>
32713270

@@ -3275,8 +3274,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
32753274
(references any OID column)
32763275
</para>
32773276
<para>
3278-
The OID of the specific dependent object,
3279-
or zero for a <symbol>DEPENDENCY_PIN</symbol> entry
3277+
The OID of the specific dependent object
32803278
</para></entry>
32813279
</row>
32823280

@@ -3467,19 +3465,6 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
34673465
</para>
34683466
</listitem>
34693467
</varlistentry>
3470-
3471-
<varlistentry>
3472-
<term><symbol>DEPENDENCY_PIN</symbol> (<literal>p</literal>)</term>
3473-
<listitem>
3474-
<para>
3475-
There is no dependent object; this type of entry is a signal
3476-
that the system itself depends on the referenced object, and so
3477-
that object must never be deleted. Entries of this type are
3478-
created only by <application>initdb</application>. The columns for the
3479-
dependent object contain zeroes.
3480-
</para>
3481-
</listitem>
3482-
</varlistentry>
34833468
</variablelist>
34843469

34853470
Other dependency flavors might be needed in future.
@@ -3498,6 +3483,19 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
34983483
must be satisfied.
34993484
</para>
35003485

3486+
<para>
3487+
Most objects created during <application>initdb</application> are
3488+
considered <quote>pinned</quote>, which means that the system itself
3489+
depends on them. Therefore, they are never allowed to be dropped.
3490+
Also, knowing that pinned objects will not be dropped, the dependency
3491+
mechanism doesn't bother to make <structname>pg_depend</structname>
3492+
entries showing dependencies on them. Thus, for example, a table
3493+
column of type <type>numeric</type> notionally has
3494+
a <literal>NORMAL</literal> dependency on the <type>numeric</type>
3495+
data type, but no such entry actually appears
3496+
in <structname>pg_depend</structname>.
3497+
</para>
3498+
35013499
</sect1>
35023500

35033501

@@ -6779,7 +6777,6 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
67796777
<para>
67806778
The OID of the database the dependent object is in,
67816779
or zero for a shared object
6782-
or a <symbol>SHARED_DEPENDENCY_PIN</symbol> entry
67836780
</para></entry>
67846781
</row>
67856782

@@ -6789,8 +6786,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
67896786
(references <link linkend="catalog-pg-class"><structname>pg_class</structname></link>.<structfield>oid</structfield>)
67906787
</para>
67916788
<para>
6792-
The OID of the system catalog the dependent object is in,
6793-
or zero for a <symbol>SHARED_DEPENDENCY_PIN</symbol> entry
6789+
The OID of the system catalog the dependent object is in
67946790
</para></entry>
67956791
</row>
67966792

@@ -6800,8 +6796,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
68006796
(references any OID column)
68016797
</para>
68026798
<para>
6803-
The OID of the specific dependent object,
6804-
or zero for a <symbol>SHARED_DEPENDENCY_PIN</symbol> entry
6799+
The OID of the specific dependent object
68056800
</para></entry>
68066801
</row>
68076802

@@ -6889,19 +6884,6 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
68896884
</listitem>
68906885
</varlistentry>
68916886

6892-
<varlistentry>
6893-
<term><symbol>SHARED_DEPENDENCY_PIN</symbol> (<literal>p</literal>)</term>
6894-
<listitem>
6895-
<para>
6896-
There is no dependent object; this type of entry is a signal
6897-
that the system itself depends on the referenced object, and so
6898-
that object must never be deleted. Entries of this type are
6899-
created only by <application>initdb</application>. The columns for the
6900-
dependent object contain zeroes.
6901-
</para>
6902-
</listitem>
6903-
</varlistentry>
6904-
69056887
<varlistentry>
69066888
<term><symbol>SHARED_DEPENDENCY_TABLESPACE</symbol> (<literal>t</literal>)</term>
69076889
<listitem>
@@ -6918,6 +6900,14 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
69186900
objects.
69196901
</para>
69206902

6903+
<para>
6904+
As in the <structname>pg_depend</structname> catalog, most objects
6905+
created during <application>initdb</application> are
6906+
considered <quote>pinned</quote>. No entries are made
6907+
in <structname>pg_shdepend</structname> that would have a pinned
6908+
object as either referenced or dependent object.
6909+
</para>
6910+
69216911
</sect1>
69226912

69236913
<sect1 id="catalog-pg-shdescription">

‎src/backend/access/transam/varsup.c

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -541,11 +541,11 @@ GetNewObjectId(void)
541541
* FirstNormalObjectId since that range is reserved for initdb (see
542542
* IsCatalogRelationOid()). Note we are relying on unsigned comparison.
543543
*
544-
* During initdb, we start the OID generator atFirstBootstrapObjectId, so
545-
*weonly wrap if before that point when in bootstrap or standalone mode.
544+
* During initdb, we start the OID generator atFirstGenbkiObjectId, so we
545+
* only wrap if before that point when in bootstrap or standalone mode.
546546
* The first time through this routine after normal postmaster start, the
547547
* counter will be forced up to FirstNormalObjectId. This mechanism
548-
* leaves the OIDs betweenFirstBootstrapObjectId and FirstNormalObjectId
548+
* leaves the OIDs betweenFirstGenbkiObjectId and FirstNormalObjectId
549549
* available for automatic assignment during initdb, while ensuring they
550550
* will never conflict with user-assigned OIDs.
551551
*/
@@ -560,7 +560,7 @@ GetNewObjectId(void)
560560
else
561561
{
562562
/* we may be bootstrapping, so don't enforce the full range */
563-
if (ShmemVariableCache->nextOid< ((Oid)FirstBootstrapObjectId))
563+
if (ShmemVariableCache->nextOid< ((Oid)FirstGenbkiObjectId))
564564
{
565565
/* wraparound in standalone mode (unlikely but possible) */
566566
ShmemVariableCache->nextOid=FirstNormalObjectId;
@@ -586,6 +586,47 @@ GetNewObjectId(void)
586586
returnresult;
587587
}
588588

589+
/*
590+
* SetNextObjectId
591+
*
592+
* This may only be called during initdb; it advances the OID counter
593+
* to the specified value.
594+
*/
595+
staticvoid
596+
SetNextObjectId(OidnextOid)
597+
{
598+
/* Safety check, this is only allowable during initdb */
599+
if (IsPostmasterEnvironment)
600+
elog(ERROR,"cannot advance OID counter anymore");
601+
602+
/* Taking the lock is, therefore, just pro forma; but do it anyway */
603+
LWLockAcquire(OidGenLock,LW_EXCLUSIVE);
604+
605+
if (ShmemVariableCache->nextOid>nextOid)
606+
elog(ERROR,"too late to advance OID counter to %u, it is now %u",
607+
nextOid,ShmemVariableCache->nextOid);
608+
609+
ShmemVariableCache->nextOid=nextOid;
610+
ShmemVariableCache->oidCount=0;
611+
612+
LWLockRelease(OidGenLock);
613+
}
614+
615+
/*
616+
* StopGeneratingPinnedObjectIds
617+
*
618+
* This is called once during initdb to force the OID counter up to
619+
* FirstUnpinnedObjectId. This supports letting initdb's post-bootstrap
620+
* processing create some pinned objects early on. Once it's done doing
621+
* so, it calls this (via pg_stop_making_pinned_objects()) so that the
622+
* remaining objects it makes will be considered un-pinned.
623+
*/
624+
void
625+
StopGeneratingPinnedObjectIds(void)
626+
{
627+
SetNextObjectId(FirstUnpinnedObjectId);
628+
}
629+
589630

590631
#ifdefUSE_ASSERT_CHECKING
591632

‎src/backend/access/transam/xlog.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5318,7 +5318,7 @@ BootStrapXLOG(void)
53185318
checkPoint.fullPageWrites=fullPageWrites;
53195319
checkPoint.nextXid=
53205320
FullTransactionIdFromEpochAndXid(0,FirstNormalTransactionId);
5321-
checkPoint.nextOid=FirstBootstrapObjectId;
5321+
checkPoint.nextOid=FirstGenbkiObjectId;
53225322
checkPoint.nextMulti=FirstMultiXactId;
53235323
checkPoint.nextMultiOffset=0;
53245324
checkPoint.oldestXid=FirstNormalTransactionId;

‎src/backend/catalog/catalog.c

Lines changed: 90 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include"catalog/pg_authid.h"
3232
#include"catalog/pg_database.h"
3333
#include"catalog/pg_db_role_setting.h"
34+
#include"catalog/pg_largeobject.h"
3435
#include"catalog/pg_namespace.h"
3536
#include"catalog/pg_replication_origin.h"
3637
#include"catalog/pg_shdepend.h"
@@ -120,9 +121,9 @@ bool
120121
IsCatalogRelationOid(Oidrelid)
121122
{
122123
/*
123-
* We consider a relation to be a system catalog if it hasan OID that was
124-
*manually assigned or assigned by genbki.pl. This includes all the
125-
*defined catalogs, their indexes, and their TOASTtables and indexes.
124+
* We consider a relation to be a system catalog if it hasa pinned OID.
125+
*This includes all the defined catalogs, their indexes, and their TOAST
126+
* tables and indexes.
126127
*
127128
* This rule excludes the relations in information_schema, which are not
128129
* integral to the system and can be treated the same as user relations.
@@ -132,7 +133,7 @@ IsCatalogRelationOid(Oid relid)
132133
* This test is reliable since an OID wraparound will skip this range of
133134
* OIDs; see GetNewObjectId().
134135
*/
135-
return (relid< (Oid)FirstBootstrapObjectId);
136+
return (relid< (Oid)FirstUnpinnedObjectId);
136137
}
137138

138139
/*
@@ -294,6 +295,64 @@ IsSharedRelation(Oid relationId)
294295
return false;
295296
}
296297

298+
/*
299+
* IsPinnedObject
300+
*Given the class + OID identity of a database object, report whether
301+
*it is "pinned", that is not droppable because the system requires it.
302+
*
303+
* We used to represent this explicitly in pg_depend, but that proved to be
304+
* an undesirable amount of overhead, so now we rely on an OID range test.
305+
*/
306+
bool
307+
IsPinnedObject(OidclassId,OidobjectId)
308+
{
309+
/*
310+
* Objects with OIDs above FirstUnpinnedObjectId are never pinned. Since
311+
* the OID generator skips this range when wrapping around, this check
312+
* guarantees that user-defined objects are never considered pinned.
313+
*/
314+
if (objectId >=FirstUnpinnedObjectId)
315+
return false;
316+
317+
/*
318+
* Large objects are never pinned. We need this special case because
319+
* their OIDs can be user-assigned.
320+
*/
321+
if (classId==LargeObjectRelationId)
322+
return false;
323+
324+
/*
325+
* There are a few objects defined in the catalog .dat files that, as a
326+
* matter of policy, we prefer not to treat as pinned. We used to handle
327+
* that by excluding them from pg_depend, but it's just as easy to
328+
* hard-wire their OIDs here. (If the user does indeed drop and recreate
329+
* them, they'll have new but certainly-unpinned OIDs, so no problem.)
330+
*
331+
* Checking both classId and objectId is overkill, since OIDs below
332+
* FirstGenbkiObjectId should be globally unique, but do it anyway for
333+
* robustness.
334+
*/
335+
336+
/* template1 is not pinned */
337+
if (classId==DatabaseRelationId&&
338+
objectId==TemplateDbOid)
339+
return false;
340+
341+
/* the public namespace is not pinned */
342+
if (classId==NamespaceRelationId&&
343+
objectId==PG_PUBLIC_NAMESPACE)
344+
return false;
345+
346+
/*
347+
* All other initdb-created objects are pinned. This is overkill (the
348+
* system doesn't really depend on having every last weird datatype, for
349+
* instance) but generating only the minimum required set of dependencies
350+
* seems hard, and enforcing an accurate list would be much more expensive
351+
* than the simple range test used here.
352+
*/
353+
return true;
354+
}
355+
297356

298357
/*
299358
* GetNewOidWithIndex
@@ -533,7 +592,8 @@ pg_nextoid(PG_FUNCTION_ARGS)
533592
if (!superuser())
534593
ereport(ERROR,
535594
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
536-
errmsg("must be superuser to call pg_nextoid()")));
595+
errmsg("must be superuser to call %s()",
596+
"pg_nextoid")));
537597

538598
rel=table_open(reloid,RowExclusiveLock);
539599
idx=index_open(idxoid,RowExclusiveLock);
@@ -580,5 +640,29 @@ pg_nextoid(PG_FUNCTION_ARGS)
580640
table_close(rel,RowExclusiveLock);
581641
index_close(idx,RowExclusiveLock);
582642

583-
returnnewoid;
643+
PG_RETURN_OID(newoid);
644+
}
645+
646+
/*
647+
* SQL callable interface for StopGeneratingPinnedObjectIds().
648+
*
649+
* This is only to be used by initdb, so it's intentionally not documented in
650+
* the user facing docs.
651+
*/
652+
Datum
653+
pg_stop_making_pinned_objects(PG_FUNCTION_ARGS)
654+
{
655+
/*
656+
* Belt-and-suspenders check, since StopGeneratingPinnedObjectIds will
657+
* fail anyway in non-single-user mode.
658+
*/
659+
if (!superuser())
660+
ereport(ERROR,
661+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
662+
errmsg("must be superuser to call %s()",
663+
"pg_stop_making_pinned_objects")));
664+
665+
StopGeneratingPinnedObjectIds();
666+
667+
PG_RETURN_VOID();
584668
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp