Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OID Wraparound #232

3 changes: 0 additions & 3 deletions src/backend/access/transam/varsup.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@
#include "utils/syscache.h"


/* Number of OIDs to prefetch (preallocate) per XLOG write */
timchang514 marked this conversation as resolved.
Show resolved Hide resolved
#define VAR_OID_PREFETCH 8192

/* pointer to "variable cache" in shared memory (set up by shmem.c) */
VariableCache ShmemVariableCache = NULL;

Expand Down
35 changes: 31 additions & 4 deletions src/backend/catalog/catalog.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "parser/parser.h"
#include "storage/fd.h"
#include "utils/fmgroids.h"
#include "utils/fmgrprotos.h"
Expand All @@ -53,6 +54,9 @@ IsExtendedCatalogHookType IsExtendedCatalogHook;
IsToastRelationHookType IsToastRelationHook;
IsToastClassHookType IsToastClassHook;

GetNewTempObjectId_hook_type GetNewTempObjectId_hook;
GetNewTempOidWithIndex_hook_type GetNewTempOidWithIndex_hook;

/*
* Parameters to determine when to emit a log message in
* GetNewOidWithIndex()
Expand Down Expand Up @@ -416,7 +420,7 @@ GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
/* Only system relations are supported */
Assert(IsSystemRelation(relation));

/* In bootstrap mode, we don't have any indexes to use */
/* In bootstrap mode, we don't have any indexes to use. No temp objects in bootstrap mode. */
if (IsBootstrapProcessingMode())
return GetNewObjectId();

Expand Down Expand Up @@ -513,12 +517,14 @@ GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
* created by bootstrap have preassigned OIDs, so there's no need.
*/
Oid
GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence, bool override_temp)
{
RelFileNodeBackend rnode;
char *rpath;
bool collides;
BackendId backend;
int tries = 0;
bool use_bbf_oid_buffer;

/*
* If we ever get here during pg_upgrade, there's something wrong; all
Expand Down Expand Up @@ -552,16 +558,32 @@ GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
*/
rnode.backend = backend;

use_bbf_oid_buffer = (relpersistence == RELPERSISTENCE_TEMP && sql_dialect == SQL_DIALECT_TSQL
&& GetNewTempOidWithIndex_hook && temp_oid_buffer_size > 0 && !override_temp);

do
{
CHECK_FOR_INTERRUPTS();

/* Generate the OID */
if (pg_class)
rnode.node.relNode = GetNewOidWithIndex(pg_class, ClassOidIndexId,
{
/* Temp tables use temp OID logic */
if (use_bbf_oid_buffer)
rnode.node.relNode = GetNewTempOidWithIndex_hook(pg_class, ClassOidIndexId,
Anum_pg_class_oid);
else
rnode.node.relNode = GetNewOidWithIndex(pg_class, ClassOidIndexId,
Anum_pg_class_oid);
}
else
rnode.node.relNode = GetNewObjectId();
{
/* Temp tables use temp OID logic */
if (use_bbf_oid_buffer)
rnode.node.relNode = GetNewTempObjectId_hook();
else
rnode.node.relNode = GetNewObjectId();
}

/* Check for existing file of same name */
rpath = relpath(rnode, MAIN_FORKNUM);
Expand All @@ -583,7 +605,12 @@ GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
collides = false;
}

if (use_bbf_oid_buffer && tries > temp_oid_buffer_size)
ereport(ERROR,
(errmsg("Unable to allocate oid for temp table. Drop some temporary tables or start a new session.")));

pfree(rpath);
tries++;
} while (collides);

return rnode.node.relNode;
Expand Down
2 changes: 1 addition & 1 deletion src/backend/catalog/heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1307,7 +1307,7 @@ heap_create_with_catalog(const char *relname,

if (!OidIsValid(relid))
relid = GetNewRelFileNode(reltablespace, pg_class_desc,
relpersistence);
relpersistence, false);
}

/*
Expand Down
8 changes: 6 additions & 2 deletions src/backend/catalog/index.c
Original file line number Diff line number Diff line change
Expand Up @@ -950,8 +950,12 @@ index_create(Relation heapRelation,
}
else
{
indexRelationId =
GetNewRelFileNode(tableSpaceId, pg_class, relpersistence);
/*
* Index OIDs must be kept in normal OID range due to deletion issues.
* Since deletion is sorted by OID, adding indexes to temp OID range
* causes deletion order issues.
*/
indexRelationId = GetNewRelFileNode(tableSpaceId, pg_class, relpersistence, is_enr);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/backend/catalog/pg_depend.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,8 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId,
((Form_pg_depend) GETSTRUCT(tup))->deptype == DEPENDENCY_EXTENSION)
continue;

CatalogTupleDelete(depRel, &tup->t_self);
if (!ENRdropTuple(depRel, tup))
CatalogTupleDelete(depRel, &tup->t_self);
count++;
}

Expand Down
2 changes: 2 additions & 0 deletions src/backend/catalog/toasting.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
*/
if (sql_dialect == SQL_DIALECT_TSQL && RelationIsBBFTableVariable(rel))
pg_toast_prefix = "@pg_toast";
else if (sql_dialect == SQL_DIALECT_TSQL && rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP && get_ENR_withoid(currentQueryEnv, rel->rd_id, ENR_TSQL_TEMP))
pg_toast_prefix = "#pg_toast";

snprintf(toast_relname, sizeof(toast_relname),
"%s_%u", pg_toast_prefix, relOid);
Expand Down
10 changes: 9 additions & 1 deletion src/backend/commands/cluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -734,8 +734,14 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, Oid NewAccessMethod,
* a shared rel. However, we do make the new heap mapped if the source is
* mapped. This simplifies swap_relation_files, and is absolutely
* necessary for rebuilding pg_class, for reasons explained there.
*
* We also must ensure that these temp tables are properly named in TSQL
* so that the metadata is properly cleaned up after in this function.
*/
snprintf(NewHeapName, sizeof(NewHeapName), "pg_temp_%u", OIDOldHeap);
if (sql_dialect == SQL_DIALECT_TSQL && relpersistence == RELPERSISTENCE_TEMP && get_ENR_withoid(currentQueryEnv, OIDOldHeap, ENR_TSQL_TEMP))
snprintf(NewHeapName, sizeof(NewHeapName), "#pg_temp_%u", OIDOldHeap);
timchang514 marked this conversation as resolved.
Show resolved Hide resolved
else
snprintf(NewHeapName, sizeof(NewHeapName), "pg_temp_%u", OIDOldHeap);

OIDNewHeap = heap_create_with_catalog(NewHeapName,
namespaceid,
Expand Down Expand Up @@ -1603,6 +1609,8 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
/* rename the toast table ... */
if (sql_dialect == SQL_DIALECT_TSQL && RelationIsBBFTableVariable(newrel))
pg_toast_prefix = "@pg_toast";
else if (sql_dialect == SQL_DIALECT_TSQL && newrel->rd_rel->relpersistence == RELPERSISTENCE_TEMP && get_ENR_withoid(currentQueryEnv, newrel->rd_id, ENR_TSQL_TEMP))
timchang514 marked this conversation as resolved.
Show resolved Hide resolved
pg_toast_prefix = "#pg_toast";

snprintf(NewToastName, NAMEDATALEN, "%s_%u",
pg_toast_prefix, OIDOldHeap);
Expand Down
2 changes: 1 addition & 1 deletion src/backend/commands/tablecmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -14582,7 +14582,7 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
* to allocate a new one in the new tablespace.
*/
newrelfilenode = GetNewRelFileNode(newTableSpace, NULL,
rel->rd_rel->relpersistence);
rel->rd_rel->relpersistence, false);

/* Open old and new relation */
newrnode = rel->rd_node;
Expand Down
8 changes: 8 additions & 0 deletions src/backend/utils/activity/pgstat_relation.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
#include "utils/rel.h"
#include "utils/timestamp.h"

#include "parser/parser.h"
#include "utils/queryenvironment.h"
timchang514 marked this conversation as resolved.
Show resolved Hide resolved


/* Record that's written to 2PC state file when pgstat state is persisted */
typedef struct TwoPhasePgStatRecord
Expand Down Expand Up @@ -168,6 +171,9 @@ pgstat_unlink_relation(Relation rel)
void
pgstat_create_relation(Relation rel)
{
/* Skip pg_stat */
if (sql_dialect == SQL_DIALECT_TSQL && rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
return;
pgstat_create_transactional(PGSTAT_KIND_RELATION,
rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
RelationGetRelid(rel));
Expand All @@ -182,6 +188,8 @@ pgstat_drop_relation(Relation rel)
int nest_level = GetCurrentTransactionNestLevel();
PgStat_TableStatus *pgstat_info;

if (sql_dialect == SQL_DIALECT_TSQL && rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
return;
pgstat_drop_transactional(PGSTAT_KIND_RELATION,
rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
RelationGetRelid(rel));
Expand Down
2 changes: 1 addition & 1 deletion src/backend/utils/cache/relcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -3735,7 +3735,7 @@ RelationSetNewRelfilenode(Relation relation, char persistence)
{
/* Allocate a new relfilenode */
newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace,
NULL, persistence);
NULL, persistence, false);
}
else if (relation->rd_rel->relkind == RELKIND_INDEX)
{
Expand Down
6 changes: 6 additions & 0 deletions src/backend/utils/misc/guc.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,12 @@ int ssl_renegotiation_limit;
int huge_pages;
int huge_page_size;

/*
* OIDs are stored as uint32, so we will add INT_MIN to match the range.
timchang514 marked this conversation as resolved.
Show resolved Hide resolved
*/
int temp_oid_buffer_start;
int temp_oid_buffer_size;

timchang514 marked this conversation as resolved.
Show resolved Hide resolved
/*
* These variables are all dummies that don't do anything, except in some
* cases provide the value for SHOW to display. The real state is elsewhere
Expand Down
9 changes: 9 additions & 0 deletions src/include/access/transam.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ FullTransactionIdAdvance(FullTransactionId *dest)
#define FirstUnpinnedObjectId 12000
#define FirstNormalObjectId 16384

/* Number of OIDs to prefetch (preallocate) per XLOG write */
#define VAR_OID_PREFETCH 8192

/*
* VariableCache is a data structure in shared memory that is used to track
* OID and XID assignment state. For largely historical reasons, there is
Expand Down Expand Up @@ -252,6 +255,12 @@ typedef struct VariableCacheData
*/
TransactionId oldestClogXid; /* oldest it's safe to look up in clog */

/*
* This field is also protected by OidGenLock. For tempOidStart, Shmem will
* be the source of truth, as another process may have gotten there first and
* updated the start.
*/
timchang514 marked this conversation as resolved.
Show resolved Hide resolved
Oid tempOidStart;
} VariableCacheData;

typedef VariableCacheData *VariableCache;
Expand Down
8 changes: 7 additions & 1 deletion src/include/catalog/catalog.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ extern bool IsPinnedObject(Oid classId, Oid objectId);
extern Oid GetNewOidWithIndex(Relation relation, Oid indexId,
AttrNumber oidcolumn);
extern Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class,
char relpersistence);
char relpersistence, bool override_temp);

typedef Oid (*GetNewTempObjectId_hook_type) (void);
extern GetNewTempObjectId_hook_type GetNewTempObjectId_hook;

typedef Oid (*GetNewTempOidWithIndex_hook_type) (Relation relation, Oid indexId, AttrNumber oidcolumn);
extern GetNewTempOidWithIndex_hook_type GetNewTempOidWithIndex_hook;

typedef bool (*IsExtendedCatalogHookType) (Oid relationId);
extern IsExtendedCatalogHookType IsExtendedCatalogHook;
Expand Down
3 changes: 3 additions & 0 deletions src/include/utils/guc.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,9 @@ extern PGDLLIMPORT int temp_file_limit;

extern PGDLLIMPORT int num_temp_buffers;

extern PGDLLIMPORT int temp_oid_buffer_start;
extern PGDLLIMPORT int temp_oid_buffer_size;
timchang514 marked this conversation as resolved.
Show resolved Hide resolved

extern PGDLLIMPORT char *cluster_name;
extern PGDLLIMPORT char *ConfigFileName;
extern PGDLLIMPORT char *HbaFileName;
Expand Down
Loading