Skip to content

Commit b14e9ce

Browse files
committed
Extend PgStat_HashKey.objid from 4 to 8 bytes
This opens the possibility to define keys for more types of statistics kinds in PgStat_HashKey, the first case being 8-byte query IDs for statistics like pg_stat_statements. This increases the size of PgStat_HashKey from 12 to 16 bytes, while PgStatShared_HashEntry, entry stored in the dshash for pgstats, keeps the same size due to alignment. xl_xact_stats_item, that tracks the stats items to drop in commit WAL records, is increased from 12 to 16 bytes. Note that individual chunks in commit WAL records should be multiples of sizeof(int), hence 8-byte object IDs are stored as two uint32, based on a suggestion from Heikki Linnakangas. While on it, the field of PgStat_HashKey is renamed from "objoid" to "objid", as for some stats kinds this field does not refer to OIDs but just IDs, like for replication slot stats. This commit bumps the following format variables: - PGSTAT_FILE_FORMAT_ID, as PgStat_HashKey is written to the stats file for non-serialized stats kinds in the dshash table. - XLOG_PAGE_MAGIC for the changes in xl_xact_stats_item. - Catalog version, for the SQL function pg_stat_have_stats(). Reviewed-by: Bertrand Drouvot Discussion: https://postgr.es/m/ZsvTS9EW79Up8I62@paquier.xyz
1 parent ac04aa8 commit b14e9ce

File tree

17 files changed

+98
-75
lines changed

17 files changed

+98
-75
lines changed

src/backend/access/rmgrdesc/xactdesc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,13 @@ xact_desc_stats(StringInfo buf, const char *label,
319319
appendStringInfo(buf, "; %sdropped stats:", label);
320320
for (i = 0; i < ndropped; i++)
321321
{
322-
appendStringInfo(buf, " %d/%u/%u",
322+
uint64 objid =
323+
((uint64) dropped_stats[i].objid_hi) << 32 | dropped_stats[i].objid_lo;
324+
325+
appendStringInfo(buf, " %d/%u/%llu",
323326
dropped_stats[i].kind,
324327
dropped_stats[i].dboid,
325-
dropped_stats[i].objoid);
328+
(unsigned long long) objid);
326329
}
327330
}
328331
}

src/backend/catalog/system_functions.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_function_counters(oid) FROM publ
684684

685685
REVOKE EXECUTE ON FUNCTION pg_stat_reset_replication_slot(text) FROM public;
686686

687-
REVOKE EXECUTE ON FUNCTION pg_stat_have_stats(text, oid, oid) FROM public;
687+
REVOKE EXECUTE ON FUNCTION pg_stat_have_stats(text, oid, int8) FROM public;
688688

689689
REVOKE EXECUTE ON FUNCTION pg_stat_reset_subscription_stats(oid) FROM public;
690690

src/backend/utils/activity/pgstat.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ pgstat_reset_counters(void)
846846
* GRANT system.
847847
*/
848848
void
849-
pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid)
849+
pgstat_reset(PgStat_Kind kind, Oid dboid, uint64 objid)
850850
{
851851
const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
852852
TimestampTz ts = GetCurrentTimestamp();
@@ -855,7 +855,7 @@ pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid)
855855
Assert(!pgstat_get_kind_info(kind)->fixed_amount);
856856

857857
/* reset the "single counter" */
858-
pgstat_reset_entry(kind, dboid, objoid, ts);
858+
pgstat_reset_entry(kind, dboid, objid, ts);
859859

860860
if (!kind_info->accessed_across_databases)
861861
pgstat_reset_database_timestamp(dboid, ts);
@@ -926,7 +926,7 @@ pgstat_clear_snapshot(void)
926926
}
927927

928928
void *
929-
pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
929+
pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
930930
{
931931
PgStat_HashKey key;
932932
PgStat_EntryRef *entry_ref;
@@ -941,7 +941,7 @@ pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
941941

942942
key.kind = kind;
943943
key.dboid = dboid;
944-
key.objoid = objoid;
944+
key.objid = objid;
945945

946946
/* if we need to build a full snapshot, do so */
947947
if (pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_SNAPSHOT)
@@ -967,7 +967,7 @@ pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
967967

968968
pgStatLocal.snapshot.mode = pgstat_fetch_consistency;
969969

970-
entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, false, NULL);
970+
entry_ref = pgstat_get_entry_ref(kind, dboid, objid, false, NULL);
971971

972972
if (entry_ref == NULL || entry_ref->shared_entry->dropped)
973973
{
@@ -1036,13 +1036,13 @@ pgstat_get_stat_snapshot_timestamp(bool *have_snapshot)
10361036
}
10371037

10381038
bool
1039-
pgstat_have_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
1039+
pgstat_have_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
10401040
{
10411041
/* fixed-numbered stats always exist */
10421042
if (pgstat_get_kind_info(kind)->fixed_amount)
10431043
return true;
10441044

1045-
return pgstat_get_entry_ref(kind, dboid, objoid, false, NULL) != NULL;
1045+
return pgstat_get_entry_ref(kind, dboid, objid, false, NULL) != NULL;
10461046
}
10471047

10481048
/*
@@ -1257,7 +1257,7 @@ pgstat_build_snapshot_fixed(PgStat_Kind kind)
12571257
* created, false otherwise.
12581258
*/
12591259
PgStat_EntryRef *
1260-
pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created_entry)
1260+
pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, uint64 objid, bool *created_entry)
12611261
{
12621262
PgStat_EntryRef *entry_ref;
12631263

@@ -1272,7 +1272,7 @@ pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created
12721272
ALLOCSET_SMALL_SIZES);
12731273
}
12741274

1275-
entry_ref = pgstat_get_entry_ref(kind, dboid, objoid,
1275+
entry_ref = pgstat_get_entry_ref(kind, dboid, objid,
12761276
true, created_entry);
12771277

12781278
if (entry_ref->pending == NULL)
@@ -1295,11 +1295,11 @@ pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created
12951295
* that it shouldn't be needed.
12961296
*/
12971297
PgStat_EntryRef *
1298-
pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
1298+
pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
12991299
{
13001300
PgStat_EntryRef *entry_ref;
13011301

1302-
entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, false, NULL);
1302+
entry_ref = pgstat_get_entry_ref(kind, dboid, objid, false, NULL);
13031303

13041304
if (entry_ref == NULL || entry_ref->pending == NULL)
13051305
return NULL;
@@ -1648,8 +1648,9 @@ pgstat_write_statsfile(XLogRecPtr redo)
16481648
*/
16491649
if (!pgstat_is_kind_valid(ps->key.kind))
16501650
{
1651-
elog(WARNING, "found unknown stats entry %u/%u/%u",
1652-
ps->key.kind, ps->key.dboid, ps->key.objoid);
1651+
elog(WARNING, "found unknown stats entry %u/%u/%llu",
1652+
ps->key.kind, ps->key.dboid,
1653+
(unsigned long long) ps->key.objid);
16531654
continue;
16541655
}
16551656

@@ -1885,8 +1886,9 @@ pgstat_read_statsfile(XLogRecPtr redo)
18851886

18861887
if (!pgstat_is_kind_valid(key.kind))
18871888
{
1888-
elog(WARNING, "invalid stats kind for entry %u/%u/%u of type %c",
1889-
key.kind, key.dboid, key.objoid, t);
1889+
elog(WARNING, "invalid stats kind for entry %u/%u/%llu of type %c",
1890+
key.kind, key.dboid,
1891+
(unsigned long long) key.objid, t);
18901892
goto error;
18911893
}
18921894
}
@@ -1957,8 +1959,9 @@ pgstat_read_statsfile(XLogRecPtr redo)
19571959
if (found)
19581960
{
19591961
dshash_release_lock(pgStatLocal.shared_hash, p);
1960-
elog(WARNING, "found duplicate stats entry %u/%u/%u of type %c",
1961-
key.kind, key.dboid, key.objoid, t);
1962+
elog(WARNING, "found duplicate stats entry %u/%u/%llu of type %c",
1963+
key.kind, key.dboid,
1964+
(unsigned long long) key.objid, t);
19621965
goto error;
19631966
}
19641967

@@ -1969,8 +1972,9 @@ pgstat_read_statsfile(XLogRecPtr redo)
19691972
pgstat_get_entry_data(key.kind, header),
19701973
pgstat_get_entry_len(key.kind)))
19711974
{
1972-
elog(WARNING, "could not read data for entry %u/%u/%u of type %c",
1973-
key.kind, key.dboid, key.objoid, t);
1975+
elog(WARNING, "could not read data for entry %u/%u/%llu of type %c",
1976+
key.kind, key.dboid,
1977+
(unsigned long long) key.objid, t);
19741978
goto error;
19751979
}
19761980

src/backend/utils/activity/pgstat_replslot.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,9 @@ pgstat_replslot_to_serialized_name_cb(const PgStat_HashKey *key, const PgStatSha
193193
* isn't allowed to change at this point, we can assume that a slot exists
194194
* at the offset.
195195
*/
196-
if (!ReplicationSlotName(key->objoid, name))
197-
elog(ERROR, "could not find name for replication slot index %u",
198-
key->objoid);
196+
if (!ReplicationSlotName(key->objid, name))
197+
elog(ERROR, "could not find name for replication slot index %llu",
198+
(unsigned long long) key->objid);
199199
}
200200

201201
bool
@@ -209,7 +209,7 @@ pgstat_replslot_from_serialized_name_cb(const NameData *name, PgStat_HashKey *ke
209209

210210
key->kind = PGSTAT_KIND_REPLSLOT;
211211
key->dboid = InvalidOid;
212-
key->objoid = idx;
212+
key->objid = idx;
213213

214214
return true;
215215
}

src/backend/utils/activity/pgstat_shmem.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -429,10 +429,10 @@ pgstat_get_entry_ref_cached(PgStat_HashKey key, PgStat_EntryRef **entry_ref_p)
429429
* if the entry is newly created, false otherwise.
430430
*/
431431
PgStat_EntryRef *
432-
pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid, bool create,
432+
pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create,
433433
bool *created_entry)
434434
{
435-
PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objoid = objoid};
435+
PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objid = objid};
436436
PgStatShared_HashEntry *shhashent;
437437
PgStatShared_Common *shheader = NULL;
438438
PgStat_EntryRef *entry_ref;
@@ -644,13 +644,13 @@ pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
644644
* Helper function to fetch and lock shared stats.
645645
*/
646646
PgStat_EntryRef *
647-
pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, Oid objoid,
647+
pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, uint64 objid,
648648
bool nowait)
649649
{
650650
PgStat_EntryRef *entry_ref;
651651

652652
/* find shared table stats entry corresponding to the local entry */
653-
entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, true, NULL);
653+
entry_ref = pgstat_get_entry_ref(kind, dboid, objid, true, NULL);
654654

655655
/* lock the shared entry to protect the content, skip if failed */
656656
if (!pgstat_lock_entry(entry_ref, nowait))
@@ -820,9 +820,10 @@ pgstat_drop_entry_internal(PgStatShared_HashEntry *shent,
820820
*/
821821
if (shent->dropped)
822822
elog(ERROR,
823-
"trying to drop stats entry already dropped: kind=%s dboid=%u objoid=%u refcount=%u",
823+
"trying to drop stats entry already dropped: kind=%s dboid=%u objid=%llu refcount=%u",
824824
pgstat_get_kind_info(shent->key.kind)->name,
825-
shent->key.dboid, shent->key.objoid,
825+
shent->key.dboid,
826+
(unsigned long long) shent->key.objid,
826827
pg_atomic_read_u32(&shent->refcount));
827828
shent->dropped = true;
828829

@@ -905,9 +906,9 @@ pgstat_drop_database_and_contents(Oid dboid)
905906
* pgstat_gc_entry_refs().
906907
*/
907908
bool
908-
pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
909+
pgstat_drop_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
909910
{
910-
PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objoid = objoid};
911+
PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objid = objid};
911912
PgStatShared_HashEntry *shent;
912913
bool freed = true;
913914

@@ -980,13 +981,13 @@ shared_stat_reset_contents(PgStat_Kind kind, PgStatShared_Common *header,
980981
* Reset one variable-numbered stats entry.
981982
*/
982983
void
983-
pgstat_reset_entry(PgStat_Kind kind, Oid dboid, Oid objoid, TimestampTz ts)
984+
pgstat_reset_entry(PgStat_Kind kind, Oid dboid, uint64 objid, TimestampTz ts)
984985
{
985986
PgStat_EntryRef *entry_ref;
986987

987988
Assert(!pgstat_get_kind_info(kind)->fixed_amount);
988989

989-
entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, false, NULL);
990+
entry_ref = pgstat_get_entry_ref(kind, dboid, objid, false, NULL);
990991
if (!entry_ref || entry_ref->shared_entry->dropped)
991992
return;
992993

src/backend/utils/activity/pgstat_xact.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,15 @@ AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit)
7777
PgStat_PendingDroppedStatsItem *pending =
7878
dclist_container(PgStat_PendingDroppedStatsItem, node, iter.cur);
7979
xl_xact_stats_item *it = &pending->item;
80+
uint64 objid = ((uint64) it->objid_hi) << 32 | it->objid_lo;
8081

8182
if (isCommit && !pending->is_create)
8283
{
8384
/*
8485
* Transaction that dropped an object committed. Drop the stats
8586
* too.
8687
*/
87-
if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
88+
if (!pgstat_drop_entry(it->kind, it->dboid, objid))
8889
not_freed_count++;
8990
}
9091
else if (!isCommit && pending->is_create)
@@ -93,7 +94,7 @@ AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit)
9394
* Transaction that created an object aborted. Drop the stats
9495
* associated with the object.
9596
*/
96-
if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
97+
if (!pgstat_drop_entry(it->kind, it->dboid, objid))
9798
not_freed_count++;
9899
}
99100

@@ -149,6 +150,7 @@ AtEOSubXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state,
149150
PgStat_PendingDroppedStatsItem *pending =
150151
dclist_container(PgStat_PendingDroppedStatsItem, node, iter.cur);
151152
xl_xact_stats_item *it = &pending->item;
153+
uint64 objid = ((uint64) it->objid_hi) << 32 | it->objid_lo;
152154

153155
dclist_delete_from(&xact_state->pending_drops, &pending->node);
154156

@@ -158,7 +160,7 @@ AtEOSubXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state,
158160
* Subtransaction creating a new stats object aborted. Drop the
159161
* stats object.
160162
*/
161-
if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
163+
if (!pgstat_drop_entry(it->kind, it->dboid, objid))
162164
not_freed_count++;
163165
pfree(pending);
164166
}
@@ -319,8 +321,9 @@ pgstat_execute_transactional_drops(int ndrops, struct xl_xact_stats_item *items,
319321
for (int i = 0; i < ndrops; i++)
320322
{
321323
xl_xact_stats_item *it = &items[i];
324+
uint64 objid = ((uint64) it->objid_hi) << 32 | it->objid_lo;
322325

323-
if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
326+
if (!pgstat_drop_entry(it->kind, it->dboid, objid))
324327
not_freed_count++;
325328
}
326329

@@ -329,7 +332,7 @@ pgstat_execute_transactional_drops(int ndrops, struct xl_xact_stats_item *items,
329332
}
330333

331334
static void
332-
create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, bool is_create)
335+
create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, uint64 objid, bool is_create)
333336
{
334337
int nest_level = GetCurrentTransactionNestLevel();
335338
PgStat_SubXactStatus *xact_state;
@@ -341,7 +344,8 @@ create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, bool
341344
drop->is_create = is_create;
342345
drop->item.kind = kind;
343346
drop->item.dboid = dboid;
344-
drop->item.objoid = objoid;
347+
drop->item.objid_lo = (uint32) objid;
348+
drop->item.objid_hi = (uint32) (objid >> 32);
345349

346350
dclist_push_tail(&xact_state->pending_drops, &drop->node);
347351
}
@@ -354,18 +358,19 @@ create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, bool
354358
* dropped.
355359
*/
356360
void
357-
pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
361+
pgstat_create_transactional(PgStat_Kind kind, Oid dboid, uint64 objid)
358362
{
359-
if (pgstat_get_entry_ref(kind, dboid, objoid, false, NULL))
363+
if (pgstat_get_entry_ref(kind, dboid, objid, false, NULL))
360364
{
361365
ereport(WARNING,
362-
errmsg("resetting existing statistics for kind %s, db=%u, oid=%u",
363-
(pgstat_get_kind_info(kind))->name, dboid, objoid));
366+
errmsg("resetting existing statistics for kind %s, db=%u, oid=%llu",
367+
(pgstat_get_kind_info(kind))->name, dboid,
368+
(unsigned long long) objid));
364369

365-
pgstat_reset(kind, dboid, objoid);
370+
pgstat_reset(kind, dboid, objid);
366371
}
367372

368-
create_drop_transactional_internal(kind, dboid, objoid, /* create */ true);
373+
create_drop_transactional_internal(kind, dboid, objid, /* create */ true);
369374
}
370375

371376
/*
@@ -376,7 +381,7 @@ pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
376381
* alive.
377382
*/
378383
void
379-
pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
384+
pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, uint64 objid)
380385
{
381-
create_drop_transactional_internal(kind, dboid, objoid, /* create */ false);
386+
create_drop_transactional_internal(kind, dboid, objid, /* create */ false);
382387
}

src/backend/utils/adt/pgstatfuncs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,8 +2046,8 @@ pg_stat_have_stats(PG_FUNCTION_ARGS)
20462046
{
20472047
char *stats_type = text_to_cstring(PG_GETARG_TEXT_P(0));
20482048
Oid dboid = PG_GETARG_OID(1);
2049-
Oid objoid = PG_GETARG_OID(2);
2049+
uint64 objid = PG_GETARG_INT64(2);
20502050
PgStat_Kind kind = pgstat_get_kind_from_str(stats_type);
20512051

2052-
PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
2052+
PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objid));
20532053
}

src/include/access/xact.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,13 @@ typedef struct xl_xact_stats_item
283283
{
284284
int kind;
285285
Oid dboid;
286-
Oid objoid;
286+
287+
/*
288+
* This stores the value of PgStat_HashKey.objid as two uint32 as all the
289+
* fields of xl_xact_xinfo should be multiples of size(int).
290+
*/
291+
uint32 objid_lo;
292+
uint32 objid_hi;
287293
} xl_xact_stats_item;
288294

289295
typedef struct xl_xact_stats_items

0 commit comments

Comments
 (0)