Skip to content

Commit f577919

Browse files
committed
Add pinning_backends column to the pg_buffercache extension.
The new column shows how many backends have a buffer pinned. That can be useful during development or to diagnose production issues e.g. caused by vacuum waiting for cleanup locks. To handle upgrades transparently - the extension might be used in views - deal with callers expecting the old number of columns. Reviewed by Fujii Masao and Rajeev rastogi.
1 parent ce48605 commit f577919

File tree

6 files changed

+58
-6
lines changed

6 files changed

+58
-6
lines changed

contrib/pg_buffercache/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ MODULE_big = pg_buffercache
44
OBJS = pg_buffercache_pages.o $(WIN32RES)
55

66
EXTENSION = pg_buffercache
7-
DATA = pg_buffercache--1.0.sql pg_buffercache--unpackaged--1.0.sql
7+
DATA = pg_buffercache--1.1.sql pg_buffercache--1.0--1.1.sql pg_buffercache--unpackaged--1.0.sql
88
PGFILEDESC = "pg_buffercache - monitoring of shared buffer cache in real-time"
99

1010
ifdef USE_PGXS
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* contrib/pg_buffercache/pg_buffercache--1.0--1.1.sql */
2+
3+
-- complain if script is sourced in psql, rather than via ALTER EXTENSION
4+
\echo Use "ALTER EXTENSION pg_buffercache UPDATE TO '1.1'" to load this file. \quit
5+
6+
-- Upgrade view to 1.1. format
7+
CREATE OR REPLACE VIEW pg_buffercache AS
8+
SELECT P.* FROM pg_buffercache_pages() AS P
9+
(bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
10+
relforknumber int2, relblocknumber int8, isdirty bool, usagecount int2,
11+
pinning_backends int4);

contrib/pg_buffercache/pg_buffercache--1.0.sql renamed to contrib/pg_buffercache/pg_buffercache--1.1.sql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* contrib/pg_buffercache/pg_buffercache--1.0.sql */
1+
/* contrib/pg_buffercache/pg_buffercache--1.1.sql */
22

33
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
44
\echo Use "CREATE EXTENSION pg_buffercache" to load this file. \quit
@@ -13,7 +13,8 @@ LANGUAGE C;
1313
CREATE VIEW pg_buffercache AS
1414
SELECT P.* FROM pg_buffercache_pages() AS P
1515
(bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
16-
relforknumber int2, relblocknumber int8, isdirty bool, usagecount int2);
16+
relforknumber int2, relblocknumber int8, isdirty bool, usagecount int2,
17+
pinning_backends int4);
1718

1819
-- Don't want these to be available to public.
1920
REVOKE ALL ON FUNCTION pg_buffercache_pages() FROM PUBLIC;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pg_buffercache extension
22
comment = 'examine the shared buffer cache'
3-
default_version = '1.0'
3+
default_version = '1.1'
44
module_pathname = '$libdir/pg_buffercache'
55
relocatable = true

contrib/pg_buffercache/pg_buffercache_pages.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
#include "storage/bufmgr.h"
1616

1717

18-
#define NUM_BUFFERCACHE_PAGES_ELEM 8
18+
#define NUM_BUFFERCACHE_PAGES_MIN_ELEM 8
19+
#define NUM_BUFFERCACHE_PAGES_ELEM 9
1920

2021
PG_MODULE_MAGIC;
2122

@@ -33,6 +34,12 @@ typedef struct
3334
bool isvalid;
3435
bool isdirty;
3536
uint16 usagecount;
37+
/*
38+
* An int32 is sufficiently large, as MAX_BACKENDS prevents a buffer from
39+
* being pinned by too many backends and each backend will only pin once
40+
* because of bufmgr.c's PrivateRefCount array.
41+
*/
42+
int32 pinning_backends;
3643
} BufferCachePagesRec;
3744

3845

@@ -60,6 +67,7 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
6067
MemoryContext oldcontext;
6168
BufferCachePagesContext *fctx; /* User function context. */
6269
TupleDesc tupledesc;
70+
TupleDesc expected_tupledesc;
6371
HeapTuple tuple;
6472

6573
if (SRF_IS_FIRSTCALL())
@@ -75,8 +83,23 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
7583
/* Create a user function context for cross-call persistence */
7684
fctx = (BufferCachePagesContext *) palloc(sizeof(BufferCachePagesContext));
7785

86+
/*
87+
* To smoothly support upgrades from version 1.0 of this extension
88+
* transparently handle the (non-)existance of the pinning_backends
89+
* column. We unfortunately have to get the result type for that... -
90+
* we can't use the result type determined by the function definition
91+
* without potentially crashing when somebody uses the old (or even
92+
* wrong) function definition though.
93+
*/
94+
if (get_call_result_type(fcinfo, NULL, &expected_tupledesc) != TYPEFUNC_COMPOSITE)
95+
elog(ERROR, "return type must be a row type");
96+
97+
if (expected_tupledesc->natts < NUM_BUFFERCACHE_PAGES_MIN_ELEM ||
98+
expected_tupledesc->natts > NUM_BUFFERCACHE_PAGES_ELEM)
99+
elog(ERROR, "incorrect number of output arguments");
100+
78101
/* Construct a tuple descriptor for the result rows. */
79-
tupledesc = CreateTemplateTupleDesc(NUM_BUFFERCACHE_PAGES_ELEM, false);
102+
tupledesc = CreateTemplateTupleDesc(expected_tupledesc->natts, false);
80103
TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid",
81104
INT4OID, -1, 0);
82105
TupleDescInitEntry(tupledesc, (AttrNumber) 2, "relfilenode",
@@ -94,6 +117,10 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
94117
TupleDescInitEntry(tupledesc, (AttrNumber) 8, "usage_count",
95118
INT2OID, -1, 0);
96119

120+
if (expected_tupledesc->natts == NUM_BUFFERCACHE_PAGES_ELEM)
121+
TupleDescInitEntry(tupledesc, (AttrNumber) 9, "pinning_backends",
122+
INT4OID, -1, 0);
123+
97124
fctx->tupdesc = BlessTupleDesc(tupledesc);
98125

99126
/* Allocate NBuffers worth of BufferCachePagesRec records. */
@@ -131,6 +158,7 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
131158
fctx->record[i].forknum = bufHdr->tag.forkNum;
132159
fctx->record[i].blocknum = bufHdr->tag.blockNum;
133160
fctx->record[i].usagecount = bufHdr->usage_count;
161+
fctx->record[i].pinning_backends = bufHdr->refcount;
134162

135163
if (bufHdr->flags & BM_DIRTY)
136164
fctx->record[i].isdirty = true;
@@ -185,6 +213,8 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
185213
nulls[5] = true;
186214
nulls[6] = true;
187215
nulls[7] = true;
216+
/* unused for v1.0 callers, but the array is always long enough */
217+
nulls[8] = true;
188218
}
189219
else
190220
{
@@ -202,6 +232,9 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
202232
nulls[6] = false;
203233
values[7] = Int16GetDatum(fctx->record[i].usagecount);
204234
nulls[7] = false;
235+
/* unused for v1.0 callers, but the array is always long enough */
236+
values[8] = Int32GetDatum(fctx->record[i].pinning_backends);
237+
nulls[8] = false;
205238
}
206239

207240
/* Build and return the tuple. */

doc/src/sgml/pgbuffercache.sgml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@
106106
<entry>Clock-sweep access count</entry>
107107
</row>
108108

109+
<row>
110+
<entry><structfield>pinning_backends</structfield></entry>
111+
<entry><type>integer</type></entry>
112+
<entry></entry>
113+
<entry>Number of backends pinning this buffer</entry>
114+
</row>
115+
109116
</tbody>
110117
</tgroup>
111118
</table>

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy