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

Commit122376f

Browse files
Show record information in pg_get_wal_block_info.
Expand the output parameters in pg_walinspect's pg_get_wal_block_infofunction to return additional information that was previously onlyavailable from pg_walinspect's pg_get_wal_records_info function. Someof the details are attributed to individual block references, ratherthan aggregated into whole-record values, since the function returns onerow per block reference per WAL record (unlike pg_get_wal_records_info,which always returns one row per WAL record).This structure is much easier to work with when writing queries thattrack how individual blocks changed over time, or when attributing coststo individual blocks (not WAL records) is useful.This is the second time that pg_get_wal_block_info has been enhanced inrecent weeks. Commit9ecb134 expanded on the original version of thefunction added in commitc31cf1c (where it first appeared under thename pg_get_wal_fpi_info). There still hasn't been a stable releasesince commitc31cf1c, so no bump in the pg_walinspect extensionversion.Author: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>Author: Peter Geoghegan <pg@bowt.ie>Reviewed-By: Peter Geoghegan <pg@bowt.ie>Reviewed-By: Kyotaro HORIGUCHI <horikyota.ntt@gmail.com>Discussion:https://postgr.es/m/CALj2ACVRK5=Z+2ZVsjgTTSkfEnQzCuwny7iigpG7g1btk4Ws2A@mail.gmail.com
1 parent63cc202 commit122376f

File tree

5 files changed

+273
-160
lines changed

5 files changed

+273
-160
lines changed

‎contrib/pg_walinspect/expected/pg_walinspect.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ UPDATE sample_tbl SET col1 = col1 + 1 WHERE col1 = 1;
121121
SELECT pg_current_wal_lsn() AS wal_lsn4 \gset
122122
-- Check if we get block data from WAL record.
123123
SELECT COUNT(*) >= 1 AS ok FROM pg_get_wal_block_info(:'wal_lsn3', :'wal_lsn4')
124-
WHERE relfilenode = :'sample_tbl_oid' ANDblockdata IS NOT NULL;
124+
WHERE relfilenode = :'sample_tbl_oid' ANDblock_data IS NOT NULL;
125125
ok
126126
----
127127
t
@@ -134,7 +134,7 @@ UPDATE sample_tbl SET col1 = col1 + 1 WHERE col1 = 2;
134134
SELECT pg_current_wal_lsn() AS wal_lsn6 \gset
135135
-- Check if we get FPI from WAL record.
136136
SELECT COUNT(*) >= 1 AS ok FROM pg_get_wal_block_info(:'wal_lsn5', :'wal_lsn6')
137-
WHERE relfilenode = :'sample_tbl_oid' ANDfpi IS NOT NULL;
137+
WHERE relfilenode = :'sample_tbl_oid' ANDblock_fpi_data IS NOT NULL;
138138
ok
139139
----
140140
t

‎contrib/pg_walinspect/pg_walinspect--1.0--1.1.sql

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,26 @@ DROP FUNCTION pg_get_wal_stats_till_end_of_wal(pg_lsn, boolean);
1212
--
1313
CREATEFUNCTIONpg_get_wal_block_info(IN start_lsn pg_lsn,
1414
IN end_lsn pg_lsn,
15-
OUT lsn pg_lsn,
16-
OUT blockid int2,
15+
OUT start_lsn pg_lsn,
16+
OUT end_lsn pg_lsn,
17+
OUT prev_lsn pg_lsn,
18+
OUT block_id int2,
1719
OUT reltablespaceoid,
1820
OUT reldatabaseoid,
1921
OUT relfilenodeoid,
22+
OUT relforknumber int2,
2023
OUT relblocknumber int8,
21-
OUT forknametext,
22-
OUT blockdatabytea,
23-
OUT fpibytea,
24-
OUT fpilen int4,
25-
OUT fpiinfotext[]
24+
OUT xid xid,
25+
OUT resource_managertext,
26+
OUT record_typetext,
27+
OUT record_length int4,
28+
OUT main_data_length int4,
29+
OUT block_data_length int4,
30+
OUT block_fpi_length int4,
31+
OUT block_fpi_infotext[],
32+
OUT descriptiontext,
33+
OUT block_databytea,
34+
OUT block_fpi_databytea
2635
)
2736
RETURNS SETOF record
2837
AS'MODULE_PATHNAME','pg_get_wal_block_info'

‎contrib/pg_walinspect/pg_walinspect.c

Lines changed: 120 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -176,24 +176,29 @@ ReadNextXLogRecord(XLogReaderState *xlogreader)
176176
}
177177

178178
/*
179-
* Get a single WAL record info.
179+
* Output values that make up a row describing caller's WAL record.
180+
*
181+
* This function leaks memory. Caller may need to use its own custom memory
182+
* context.
183+
*
184+
* Keep this in sync with GetWALBlockInfo.
180185
*/
181186
staticvoid
182187
GetWALRecordInfo(XLogReaderState*record,Datum*values,
183188
bool*nulls,uint32ncols)
184189
{
185-
constchar*id;
190+
constchar*record_type;
186191
RmgrDatadesc;
187192
uint32fpi_len=0;
188193
StringInfoDatarec_desc;
189194
StringInfoDatarec_blk_ref;
190195
inti=0;
191196

192197
desc=GetRmgr(XLogRecGetRmid(record));
193-
id=desc.rm_identify(XLogRecGetInfo(record));
198+
record_type=desc.rm_identify(XLogRecGetInfo(record));
194199

195-
if (id==NULL)
196-
id=psprintf("UNKNOWN (%x)",XLogRecGetInfo(record)& ~XLR_INFO_MASK);
200+
if (record_type==NULL)
201+
record_type=psprintf("UNKNOWN (%x)",XLogRecGetInfo(record)& ~XLR_INFO_MASK);
197202

198203
initStringInfo(&rec_desc);
199204
desc.rm_desc(&rec_desc,record);
@@ -209,7 +214,7 @@ GetWALRecordInfo(XLogReaderState *record, Datum *values,
209214
values[i++]=LSNGetDatum(XLogRecGetPrev(record));
210215
values[i++]=TransactionIdGetDatum(XLogRecGetXid(record));
211216
values[i++]=CStringGetTextDatum(desc.rm_name);
212-
values[i++]=CStringGetTextDatum(id);
217+
values[i++]=CStringGetTextDatum(record_type);
213218
values[i++]=UInt32GetDatum(XLogRecGetTotalLen(record));
214219
values[i++]=UInt32GetDatum(XLogRecGetDataLen(record));
215220
values[i++]=UInt32GetDatum(fpi_len);
@@ -229,24 +234,48 @@ GetWALRecordInfo(XLogReaderState *record, Datum *values,
229234

230235

231236
/*
232-
* Store a set of block information from a single record (FPI and block
233-
* information).
237+
* Output one or more rows in rsinfo tuple store, each describing a single
238+
* block reference from caller's WAL record. (Should only be called with
239+
* records that have block references.)
240+
*
241+
* This function leaks memory. Caller may need to use its own custom memory
242+
* context.
243+
*
244+
* Keep this in sync with GetWALRecordInfo.
234245
*/
235246
staticvoid
236247
GetWALBlockInfo(FunctionCallInfofcinfo,XLogReaderState*record)
237248
{
238-
#definePG_GET_WAL_BLOCK_INFO_COLS11
249+
#definePG_GET_WAL_BLOCK_INFO_COLS20
239250
intblock_id;
240251
ReturnSetInfo*rsinfo= (ReturnSetInfo*)fcinfo->resultinfo;
252+
RmgrDatadesc;
253+
constchar*record_type;
254+
StringInfoDatarec_desc;
255+
256+
Assert(XLogRecHasAnyBlockRefs(record));
257+
258+
desc=GetRmgr(XLogRecGetRmid(record));
259+
record_type=desc.rm_identify(XLogRecGetInfo(record));
260+
261+
if (record_type==NULL)
262+
record_type=psprintf("UNKNOWN (%x)",
263+
XLogRecGetInfo(record)& ~XLR_INFO_MASK);
264+
265+
initStringInfo(&rec_desc);
266+
desc.rm_desc(&rec_desc,record);
241267

242268
for (block_id=0;block_id <=XLogRecMaxBlockId(record);block_id++)
243269
{
244270
DecodedBkpBlock*blk;
245271
BlockNumberblkno;
246272
RelFileLocatorrnode;
247-
ForkNumberfork;
273+
ForkNumberforknum;
248274
Datumvalues[PG_GET_WAL_BLOCK_INFO_COLS]= {0};
249275
boolnulls[PG_GET_WAL_BLOCK_INFO_COLS]= {0};
276+
uint32block_data_len=0,
277+
block_fpi_len=0;
278+
ArrayType*block_fpi_info=NULL;
250279
inti=0;
251280

252281
if (!XLogRecHasBlockRef(record,block_id))
@@ -255,99 +284,117 @@ GetWALBlockInfo(FunctionCallInfo fcinfo, XLogReaderState *record)
255284
blk=XLogRecGetBlock(record,block_id);
256285

257286
(void)XLogRecGetBlockTagExtended(record,block_id,
258-
&rnode,&fork,&blkno,NULL);
287+
&rnode,&forknum,&blkno,NULL);
259288

289+
/* Save block_data_len */
290+
if (blk->has_data)
291+
block_data_len=blk->data_len;
292+
293+
if (blk->has_image)
294+
{
295+
/* Block reference has an FPI, so prepare relevant output */
296+
intbitcnt;
297+
intcnt=0;
298+
Datum*flags;
299+
300+
/* Save block_fpi_len */
301+
block_fpi_len=blk->bimg_len;
302+
303+
/* Construct and save block_fpi_info */
304+
bitcnt=pg_popcount((constchar*)&blk->bimg_info,
305+
sizeof(uint8));
306+
flags= (Datum*)palloc0(sizeof(Datum)*bitcnt);
307+
if ((blk->bimg_info&BKPIMAGE_HAS_HOLE)!=0)
308+
flags[cnt++]=CStringGetTextDatum("HAS_HOLE");
309+
if (blk->apply_image)
310+
flags[cnt++]=CStringGetTextDatum("APPLY");
311+
if ((blk->bimg_info&BKPIMAGE_COMPRESS_PGLZ)!=0)
312+
flags[cnt++]=CStringGetTextDatum("COMPRESS_PGLZ");
313+
if ((blk->bimg_info&BKPIMAGE_COMPRESS_LZ4)!=0)
314+
flags[cnt++]=CStringGetTextDatum("COMPRESS_LZ4");
315+
if ((blk->bimg_info&BKPIMAGE_COMPRESS_ZSTD)!=0)
316+
flags[cnt++]=CStringGetTextDatum("COMPRESS_ZSTD");
317+
318+
Assert(cnt <=bitcnt);
319+
block_fpi_info=construct_array_builtin(flags,cnt,TEXTOID);
320+
}
321+
322+
/* start_lsn, end_lsn, prev_lsn, and blockid outputs */
260323
values[i++]=LSNGetDatum(record->ReadRecPtr);
324+
values[i++]=LSNGetDatum(record->EndRecPtr);
325+
values[i++]=LSNGetDatum(XLogRecGetPrev(record));
261326
values[i++]=Int16GetDatum(block_id);
327+
328+
/* relfile and block related outputs */
262329
values[i++]=ObjectIdGetDatum(blk->rlocator.spcOid);
263330
values[i++]=ObjectIdGetDatum(blk->rlocator.dbOid);
264331
values[i++]=ObjectIdGetDatum(blk->rlocator.relNumber);
332+
values[i++]=Int16GetDatum(forknum);
265333
values[i++]=Int64GetDatum((int64)blkno);
266334

267-
if (fork >=0&&fork <=MAX_FORKNUM)
268-
values[i++]=CStringGetTextDatum(forkNames[fork]);
335+
/* xid, resource_manager, and record_type outputs */
336+
values[i++]=TransactionIdGetDatum(XLogRecGetXid(record));
337+
values[i++]=CStringGetTextDatum(desc.rm_name);
338+
values[i++]=CStringGetTextDatum(record_type);
339+
340+
/*
341+
* record_length, main_data_length, block_data_len, and
342+
* block_fpi_length outputs
343+
*/
344+
values[i++]=UInt32GetDatum(XLogRecGetTotalLen(record));
345+
values[i++]=UInt32GetDatum(XLogRecGetDataLen(record));
346+
values[i++]=UInt32GetDatum(block_data_len);
347+
values[i++]=UInt32GetDatum(block_fpi_len);
348+
349+
/* block_fpi_info (text array) output */
350+
if (block_fpi_info)
351+
values[i++]=PointerGetDatum(block_fpi_info);
269352
else
270-
ereport(ERROR,
271-
(errcode(ERRCODE_INTERNAL_ERROR),
272-
errmsg_internal("invalid fork number: %u",fork)));
353+
nulls[i++]= true;
273354

274-
/* Block data */
355+
/* description output (describes WAL record) */
356+
if (rec_desc.len>0)
357+
values[i++]=CStringGetTextDatum(rec_desc.data);
358+
else
359+
nulls[i++]= true;
360+
361+
/* block_data output */
275362
if (blk->has_data)
276363
{
277-
bytea*raw_data;
364+
bytea*block_data;
278365

279-
/* Initialize bytea buffer to copy the data to */
280-
raw_data= (bytea*)palloc(blk->data_len+VARHDRSZ);
281-
SET_VARSIZE(raw_data,blk->data_len+VARHDRSZ);
282-
283-
/* Copy the data */
284-
memcpy(VARDATA(raw_data),blk->data,blk->data_len);
285-
values[i++]=PointerGetDatum(raw_data);
366+
block_data= (bytea*)palloc(block_data_len+VARHDRSZ);
367+
SET_VARSIZE(block_data,block_data_len+VARHDRSZ);
368+
memcpy(VARDATA(block_data),blk->data,block_data_len);
369+
values[i++]=PointerGetDatum(block_data);
286370
}
287371
else
288-
{
289-
/* No data, so set this field to NULL */
290372
nulls[i++]= true;
291-
}
292373

374+
/* block_fpi_data output */
293375
if (blk->has_image)
294376
{
295377
PGAlignedBlockbuf;
296378
Pagepage;
297-
bytea*raw_page;
298-
intbitcnt;
299-
intcnt=0;
300-
Datum*flags;
301-
ArrayType*a;
379+
bytea*block_fpi_data;
302380

303381
page= (Page)buf.data;
304-
305-
/* Full page image exists, so let's save it */
306382
if (!RestoreBlockImage(record,block_id,page))
307383
ereport(ERROR,
308384
(errcode(ERRCODE_INTERNAL_ERROR),
309385
errmsg_internal("%s",record->errormsg_buf)));
310386

311-
/* Initialize bytea buffer to copy the FPI to */
312-
raw_page= (bytea*)palloc(BLCKSZ+VARHDRSZ);
313-
SET_VARSIZE(raw_page,BLCKSZ+VARHDRSZ);
314-
315-
/* Take a verbatim copy of the FPI */
316-
memcpy(VARDATA(raw_page),page,BLCKSZ);
317-
318-
values[i++]=PointerGetDatum(raw_page);
319-
values[i++]=UInt32GetDatum(blk->bimg_len);
320-
321-
/* FPI flags */
322-
bitcnt=pg_popcount((constchar*)&blk->bimg_info,
323-
sizeof(uint8));
324-
/* Build set of raw flags */
325-
flags= (Datum*)palloc0(sizeof(Datum)*bitcnt);
326-
327-
if ((blk->bimg_info&BKPIMAGE_HAS_HOLE)!=0)
328-
flags[cnt++]=CStringGetTextDatum("HAS_HOLE");
329-
if (blk->apply_image)
330-
flags[cnt++]=CStringGetTextDatum("APPLY");
331-
if ((blk->bimg_info&BKPIMAGE_COMPRESS_PGLZ)!=0)
332-
flags[cnt++]=CStringGetTextDatum("COMPRESS_PGLZ");
333-
if ((blk->bimg_info&BKPIMAGE_COMPRESS_LZ4)!=0)
334-
flags[cnt++]=CStringGetTextDatum("COMPRESS_LZ4");
335-
if ((blk->bimg_info&BKPIMAGE_COMPRESS_ZSTD)!=0)
336-
flags[cnt++]=CStringGetTextDatum("COMPRESS_ZSTD");
337-
338-
Assert(cnt <=bitcnt);
339-
a=construct_array_builtin(flags,cnt,TEXTOID);
340-
values[i++]=PointerGetDatum(a);
387+
block_fpi_data= (bytea*)palloc(BLCKSZ+VARHDRSZ);
388+
SET_VARSIZE(block_fpi_data,BLCKSZ+VARHDRSZ);
389+
memcpy(VARDATA(block_fpi_data),page,BLCKSZ);
390+
values[i++]=PointerGetDatum(block_fpi_data);
341391
}
342392
else
343-
{
344-
/* No full page image, so store NULLs for all its fields */
345-
memset(&nulls[i], true,3*sizeof(bool));
346-
i+=3;
347-
}
393+
nulls[i++]= true;
348394

349395
Assert(i==PG_GET_WAL_BLOCK_INFO_COLS);
350396

397+
/* Store a tuple for this block reference */
351398
tuplestore_putvalues(rsinfo->setResult,rsinfo->setDesc,
352399
values,nulls);
353400
}
@@ -356,11 +403,7 @@ GetWALBlockInfo(FunctionCallInfo fcinfo, XLogReaderState *record)
356403
}
357404

358405
/*
359-
* Get information about all the blocks saved in WAL records between start
360-
* and end LSNs. This produces information about the full page images with
361-
* their relation information, and the data saved in each block associated
362-
* to a record. Decompression is applied to the full page images, if
363-
* necessary.
406+
* Get WAL record info, unnested by block reference
364407
*/
365408
Datum
366409
pg_get_wal_block_info(PG_FUNCTION_ARGS)
@@ -484,7 +527,7 @@ ValidateInputLSNs(XLogRecPtr start_lsn, XLogRecPtr *end_lsn)
484527
}
485528

486529
/*
487-
* Get infoand dataof all WAL records between start LSN and end LSN.
530+
* Get info of all WAL records between start LSN and end LSN.
488531
*/
489532
staticvoid
490533
GetWALRecordsInfo(FunctionCallInfofcinfo,XLogRecPtrstart_lsn,
@@ -536,7 +579,7 @@ GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
536579
}
537580

538581
/*
539-
* Get infoand dataof all WAL records between start LSN and end LSN.
582+
* Get info of all WAL records between start LSN and end LSN.
540583
*/
541584
Datum
542585
pg_get_wal_records_info(PG_FUNCTION_ARGS)

‎contrib/pg_walinspect/sql/pg_walinspect.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ UPDATE sample_tbl SET col1 = col1 + 1 WHERE col1 = 1;
7878
SELECT pg_current_wal_lsn()AS wal_lsn4 \gset
7979
-- Check if we get block data from WAL record.
8080
SELECTCOUNT(*)>=1AS okFROM pg_get_wal_block_info(:'wal_lsn3', :'wal_lsn4')
81-
WHERE relfilenode= :'sample_tbl_oid'ANDblockdataIS NOT NULL;
81+
WHERE relfilenode= :'sample_tbl_oid'ANDblock_dataIS NOT NULL;
8282

8383
-- Force full-page image on the next update.
8484
SELECT pg_current_wal_lsn()AS wal_lsn5 \gset
@@ -87,7 +87,7 @@ UPDATE sample_tbl SET col1 = col1 + 1 WHERE col1 = 2;
8787
SELECT pg_current_wal_lsn()AS wal_lsn6 \gset
8888
-- Check if we get FPI from WAL record.
8989
SELECTCOUNT(*)>=1AS okFROM pg_get_wal_block_info(:'wal_lsn5', :'wal_lsn6')
90-
WHERE relfilenode= :'sample_tbl_oid'ANDfpiIS NOT NULL;
90+
WHERE relfilenode= :'sample_tbl_oid'ANDblock_fpi_dataIS NOT NULL;
9191

9292
-- ===================================================================
9393
-- Tests for permissions

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp