Skip to content

Commit e67432a

Browse files
ashutosh-bapatCommitfest Bot
authored andcommitted
Add system view for shared buffer lookup table
The view exposes the contents of the shared buffer lookup table for debugging, testing and investigation. TODO: It is better to place this view in pg_buffercache. But it's added as a system view since BufHashTable is not exposed outside buf_table.c. To move it to pg_buffercache, we should move the function pg_get_buffer_lookup_table() to pg_buffercache which invokes BufTableGetContent() by passing it the tuple store and tuple descriptor. BufTableGetContent fills the tuple store. The partitions are locked by pg_get_buffer_lookup_table(). Author: Ashutosh Bapat <[email protected]>
1 parent 74b41f5 commit e67432a

File tree

5 files changed

+175
-0
lines changed

5 files changed

+175
-0
lines changed

doc/src/sgml/system-views.sgml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@
7171
<entry>backend memory contexts</entry>
7272
</row>
7373

74+
<row>
75+
<entry><link linkend="view-pg-buffer-lookup-table"><structname>pg_buffer_lookup_table</structname></link></entry>
76+
<entry>shared buffer lookup table</entry>
77+
</row>
78+
7479
<row>
7580
<entry><link linkend="view-pg-config"><structname>pg_config</structname></link></entry>
7681
<entry>compile-time configuration parameters</entry>
@@ -896,6 +901,90 @@ AND c1.path[c2.level] = c2.path[c2.level];
896901
</para>
897902
</sect1>
898903

904+
<sect1 id="view-pg-buffer-lookup-table">
905+
<title><structname>pg_buffer_lookup_table</structname></title>
906+
<indexterm>
907+
<primary>pg_buffer_lookup_table</primary>
908+
</indexterm>
909+
<para>
910+
The <structname>pg_buffer_lookup_table</structname> view exposes the current
911+
contents of the shared buffer lookup table. Each row represents an entry in
912+
the lookup table mapping a relation page to the ID of buffer in which it is
913+
cached. The shared buffer lookup table is locked for a short duration while
914+
reading so as to ensure consistency. This may affect performance if this view
915+
is queried very frequently.
916+
</para>
917+
<table id="pg-buffer-lookup-table-view" xreflabel="pg_buffer_lookup_table">
918+
<title><structname>pg_buffer_lookup_table</structname> View</title>
919+
<tgroup cols="1">
920+
<thead>
921+
<row>
922+
<entry role="catalog_table_entry"><para role="column_definition">
923+
Column Type
924+
</para>
925+
<para>
926+
Description
927+
</para></entry>
928+
</row>
929+
</thead>
930+
<tbody>
931+
<row>
932+
<entry role="catalog_table_entry"><para role="column_definition">
933+
<structfield>tablespace</structfield> <type>oid</type>
934+
</para>
935+
<para>
936+
OID of the tablespace containing the relation
937+
</para></entry>
938+
</row>
939+
<row>
940+
<entry role="catalog_table_entry"><para role="column_definition">
941+
<structfield>database</structfield> <type>oid</type>
942+
</para>
943+
<para>
944+
OID of the database containing the relation (zero for shared relations)
945+
</para></entry>
946+
</row>
947+
<row>
948+
<entry role="catalog_table_entry"><para role="column_definition">
949+
<structfield>relfilenode</structfield> <type>oid</type>
950+
</para>
951+
<para>
952+
relfilenode identifying the relation
953+
</para></entry>
954+
</row>
955+
<row>
956+
<entry role="catalog_table_entry"><para role="column_definition">
957+
<structfield>forknum</structfield> <type>int2</type>
958+
</para>
959+
<para>
960+
Fork number within the relation (see <xref linkend="storage-file-layout"/>)
961+
</para></entry>
962+
</row>
963+
<row>
964+
<entry role="catalog_table_entry"><para role="column_definition">
965+
<structfield>blocknum</structfield> <type>int8</type>
966+
</para>
967+
<para>
968+
Block number within the relation
969+
</para></entry>
970+
</row>
971+
<row>
972+
<entry role="catalog_table_entry"><para role="column_definition">
973+
<structfield>bufferid</structfield> <type>int4</type>
974+
</para>
975+
<para>
976+
ID of the buffer caching the page
977+
</para></entry>
978+
</row>
979+
</tbody>
980+
</tgroup>
981+
</table>
982+
<para>
983+
Access to this view is restricted to members of the
984+
<literal>pg_read_all_stats</literal> role by default.
985+
</para>
986+
</sect1>
987+
899988
<sect1 id="view-pg-config">
900989
<title><structname>pg_config</structname></title>
901990

src/backend/catalog/system_views.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,3 +1420,10 @@ REVOKE ALL ON pg_aios FROM PUBLIC;
14201420
GRANT SELECT ON pg_aios TO pg_read_all_stats;
14211421
REVOKE EXECUTE ON FUNCTION pg_get_aios() FROM PUBLIC;
14221422
GRANT EXECUTE ON FUNCTION pg_get_aios() TO pg_read_all_stats;
1423+
1424+
CREATE VIEW pg_buffer_lookup_table AS
1425+
SELECT * FROM pg_get_buffer_lookup_table();
1426+
REVOKE ALL ON pg_buffer_lookup_table FROM PUBLIC;
1427+
GRANT SELECT ON pg_buffer_lookup_table TO pg_read_all_stats;
1428+
REVOKE EXECUTE ON FUNCTION pg_get_buffer_lookup_table() FROM PUBLIC;
1429+
GRANT EXECUTE ON FUNCTION pg_get_buffer_lookup_table() TO pg_read_all_stats;

src/backend/storage/buffer/buf_table.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@
2121
*/
2222
#include "postgres.h"
2323

24+
#include "fmgr.h"
25+
#include "funcapi.h"
2426
#include "storage/buf_internals.h"
27+
#include "storage/lwlock.h"
28+
#include "utils/rel.h"
29+
#include "utils/builtins.h"
2530

2631
/* entry for buffer lookup hashtable */
2732
typedef struct
@@ -159,3 +164,59 @@ BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
159164
if (!result) /* shouldn't happen */
160165
elog(ERROR, "shared buffer hash table corrupted");
161166
}
167+
168+
/*
169+
* SQL callable function to report contents of the shared buffer lookup table.
170+
*/
171+
Datum
172+
pg_get_buffer_lookup_table(PG_FUNCTION_ARGS)
173+
{
174+
#define PG_GET_BUFFER_LOOKUP_TABLE_COLS 6
175+
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
176+
HASH_SEQ_STATUS hstat;
177+
BufferLookupEnt *ent;
178+
Datum values[PG_GET_BUFFER_LOOKUP_TABLE_COLS];
179+
bool nulls[PG_GET_BUFFER_LOOKUP_TABLE_COLS];
180+
int i;
181+
182+
memset(nulls, 0, sizeof(nulls));
183+
184+
/*
185+
* We put all the tuples into a tuplestore in one scan of the hashtable.
186+
* This avoids any issue of the hashtable possibly changing between calls.
187+
*/
188+
InitMaterializedSRF(fcinfo, 0);
189+
190+
Assert(rsinfo->setDesc->natts == PG_GET_BUFFER_LOOKUP_TABLE_COLS);
191+
192+
/*
193+
* Lock all buffer mapping partitions to ensure a consistent view of the
194+
* hash table during the scan. Must grab LWLocks in partition-number order
195+
* to avoid LWLock deadlock.
196+
*/
197+
for (i = 0; i < NUM_BUFFER_PARTITIONS; i++)
198+
LWLockAcquire(BufMappingPartitionLockByIndex(i), LW_SHARED);
199+
200+
hash_seq_init(&hstat, SharedBufHash);
201+
while ((ent = (BufferLookupEnt *) hash_seq_search(&hstat)) != NULL)
202+
{
203+
values[0] = ObjectIdGetDatum(ent->key.spcOid);
204+
values[1] = ObjectIdGetDatum(ent->key.dbOid);
205+
values[2] = ObjectIdGetDatum(ent->key.relNumber);
206+
values[3] = ObjectIdGetDatum(ent->key.forkNum);
207+
values[4] = UInt32GetDatum(ent->key.blockNum);
208+
values[5] = Int32GetDatum(ent->id);
209+
210+
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
211+
values, nulls);
212+
}
213+
214+
/*
215+
* Release all buffer mapping partition locks in the reverse order so as
216+
* to avoid LWLock deadlock.
217+
*/
218+
for (i = NUM_BUFFER_PARTITIONS - 1; i >= 0; i--)
219+
LWLockRelease(BufMappingPartitionLockByIndex(i));
220+
221+
return (Datum) 0;
222+
}

src/include/catalog/pg_proc.dat

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8592,6 +8592,17 @@
85928592
proargmodes => '{o,o,o}', proargnames => '{name,type,size}',
85938593
prosrc => 'pg_get_dsm_registry_allocations' },
85948594

8595+
# buffer lookup table
8596+
{ oid => '5102',
8597+
descr => 'shared buffer lookup table',
8598+
proname => 'pg_get_buffer_lookup_table', prorows => '6', proretset => 't',
8599+
provolatile => 'v', prorettype => 'record',
8600+
proargtypes => '', proallargtypes => '{oid,oid,oid,int2,int8,int4}',
8601+
proargmodes => '{o,o,o,o,o,o}',
8602+
proargnames => '{tablespace,database,relfilenode,forknum,blocknum,bufferid}',
8603+
prosrc => 'pg_get_buffer_lookup_table'
8604+
},
8605+
85958606
# memory context of local backend
85968607
{ oid => '2282',
85978608
descr => 'information about all memory contexts of local backend',

src/test/regress/expected/rules.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,13 @@ pg_backend_memory_contexts| SELECT name,
13301330
free_chunks,
13311331
used_bytes
13321332
FROM pg_get_backend_memory_contexts() pg_get_backend_memory_contexts(name, ident, type, level, path, total_bytes, total_nblocks, free_bytes, free_chunks, used_bytes);
1333+
pg_buffer_lookup_table| SELECT tablespace,
1334+
database,
1335+
relfilenode,
1336+
forknum,
1337+
blocknum,
1338+
bufferid
1339+
FROM pg_get_buffer_lookup_table() pg_get_buffer_lookup_table(tablespace, database, relfilenode, forknum, blocknum, bufferid);
13331340
pg_config| SELECT name,
13341341
setting
13351342
FROM pg_config() pg_config(name, setting);

0 commit comments

Comments
 (0)