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

Commit9ecb134

Browse files
committed
pg_walinspect: pg_get_wal_fpi_info() -> pg_get_wal_block_info()
This commit reworks pg_get_wal_fpi_info() to become aware of all theblock information that can be attached to a record rather than just itsfull-page writes:- Addition of the block id as assigned by XLogRegisterBuffer(),XLogRegisterBlock() or XLogRegisterBufData().- Addition of the block data, as bytea, or NULL if none. The length ofthe block data can be guessed with length(), so there is no need tostore its length in a separate field.- Addition of the full-page image length, as counted without a hole oreven compressed.- Modification of the handling of the full-page image data. This isstill a bytea, but it could become NULL if none is assigned to a block.- Addition of the full-page image flags, tracking if a page is storedwith a hole, if it needs to be applied and the type of compressionapplied to it, as of all the BKPIMAGE_* values in xlogrecord.h.The information of each block is returned as one single record, with therecord's ReadRecPtr included to be able to join the block informationwith the existing pg_get_wal_records_info(). Note that it is perfectlypossible for a block to hold both data and full-page image.Thanks also to Kyotaro Horiguchi and Matthias van de Meent for thediscussion.This commit uses some of the work proposed by Melanie, though it hasbeen largely redesigned and rewritten by me. Bharath has helped inrefining a bit the whole.Reported-by: Melanie PlagemanAuthor: Michael Paquier, Melanie Plageman, Bharath RupireddyDiscussion:https://postgr.es/m/CAAKRu_bORebdZmcV8V4cZBzU8M_C6tDDdbiPhCZ6i-iuSXW9TA@mail.gmail.com
1 parent8da2ec3 commit9ecb134

File tree

5 files changed

+174
-86
lines changed

5 files changed

+174
-86
lines changed

‎contrib/pg_walinspect/expected/pg_walinspect.out

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,28 @@ SELECT COUNT(*) >= 1 AS ok FROM pg_get_wal_records_info(:'wal_lsn1', :'wal_lsn2'
7474
(1 row)
7575

7676
-- ===================================================================
77-
-- Tests to getfull page image (FPI) from WAL record
77+
-- Tests to getblock information from WAL record
7878
-- ===================================================================
79+
-- Update table to generate some block data
7980
SELECT pg_current_wal_lsn() AS wal_lsn3 \gset
80-
-- Force FPI on the next update.
81-
CHECKPOINT;
82-
-- Update table to generate an FPI.
83-
UPDATE sample_tbl SET col1 = col1 * 100 WHERE col1 = 1;
81+
UPDATE sample_tbl SET col1 = col1 + 1 WHERE col1 = 1;
8482
SELECT pg_current_wal_lsn() AS wal_lsn4 \gset
83+
-- Check if we get block data from WAL record.
84+
SELECT COUNT(*) >= 1 AS ok FROM pg_get_wal_block_info(:'wal_lsn3', :'wal_lsn4')
85+
WHERE relfilenode = :'sample_tbl_oid' AND blockdata IS NOT NULL;
86+
ok
87+
----
88+
t
89+
(1 row)
90+
91+
-- Force full-page image on the next update.
92+
SELECT pg_current_wal_lsn() AS wal_lsn5 \gset
93+
CHECKPOINT;
94+
UPDATE sample_tbl SET col1 = col1 + 1 WHERE col1 = 2;
95+
SELECT pg_current_wal_lsn() AS wal_lsn6 \gset
8596
-- Check if we get FPI from WAL record.
86-
SELECT COUNT(*) >= 1 AS ok FROMpg_get_wal_fpi_info(:'wal_lsn3', :'wal_lsn4')
87-
WHERE relfilenode = :'sample_tbl_oid';
97+
SELECT COUNT(*) >= 1 AS ok FROMpg_get_wal_block_info(:'wal_lsn5', :'wal_lsn6')
98+
WHERE relfilenode = :'sample_tbl_oid' AND fpi IS NOT NULL;
8899
ok
89100
----
90101
t
@@ -116,7 +127,7 @@ SELECT has_function_privilege('regress_pg_walinspect',
116127
(1 row)
117128

118129
SELECT has_function_privilege('regress_pg_walinspect',
119-
'pg_get_wal_fpi_info(pg_lsn, pg_lsn) ', 'EXECUTE'); -- no
130+
'pg_get_wal_block_info(pg_lsn, pg_lsn) ', 'EXECUTE'); -- no
120131
has_function_privilege
121132
------------------------
122133
f
@@ -146,7 +157,7 @@ SELECT has_function_privilege('regress_pg_walinspect',
146157
(1 row)
147158

148159
SELECT has_function_privilege('regress_pg_walinspect',
149-
'pg_get_wal_fpi_info(pg_lsn, pg_lsn) ', 'EXECUTE'); -- yes
160+
'pg_get_wal_block_info(pg_lsn, pg_lsn) ', 'EXECUTE'); -- yes
150161
has_function_privilege
151162
------------------------
152163
t
@@ -160,7 +171,7 @@ GRANT EXECUTE ON FUNCTION pg_get_wal_records_info(pg_lsn, pg_lsn)
160171
TO regress_pg_walinspect;
161172
GRANT EXECUTE ON FUNCTION pg_get_wal_stats(pg_lsn, pg_lsn, boolean)
162173
TO regress_pg_walinspect;
163-
GRANT EXECUTE ON FUNCTIONpg_get_wal_fpi_info(pg_lsn, pg_lsn)
174+
GRANT EXECUTE ON FUNCTIONpg_get_wal_block_info(pg_lsn, pg_lsn)
164175
TO regress_pg_walinspect;
165176
SELECT has_function_privilege('regress_pg_walinspect',
166177
'pg_get_wal_record_info(pg_lsn)', 'EXECUTE'); -- yes
@@ -184,7 +195,7 @@ SELECT has_function_privilege('regress_pg_walinspect',
184195
(1 row)
185196

186197
SELECT has_function_privilege('regress_pg_walinspect',
187-
'pg_get_wal_fpi_info(pg_lsn, pg_lsn) ', 'EXECUTE'); -- yes
198+
'pg_get_wal_block_info(pg_lsn, pg_lsn) ', 'EXECUTE'); -- yes
188199
has_function_privilege
189200
------------------------
190201
t
@@ -196,7 +207,7 @@ REVOKE EXECUTE ON FUNCTION pg_get_wal_records_info(pg_lsn, pg_lsn)
196207
FROM regress_pg_walinspect;
197208
REVOKE EXECUTE ON FUNCTION pg_get_wal_stats(pg_lsn, pg_lsn, boolean)
198209
FROM regress_pg_walinspect;
199-
REVOKE EXECUTE ON FUNCTIONpg_get_wal_fpi_info(pg_lsn, pg_lsn)
210+
REVOKE EXECUTE ON FUNCTIONpg_get_wal_block_info(pg_lsn, pg_lsn)
200211
FROM regress_pg_walinspect;
201212
-- ===================================================================
202213
-- Clean up

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,25 @@
44
\echo Use"ALTER EXTENSION pg_walinspect UPDATE TO '1.1'" to load this file. \quit
55

66
--
7-
--pg_get_wal_fpi_info()
7+
--pg_get_wal_block_info()
88
--
9-
CREATEFUNCTIONpg_get_wal_fpi_info(IN start_lsn pg_lsn,
9+
CREATEFUNCTIONpg_get_wal_block_info(IN start_lsn pg_lsn,
1010
IN end_lsn pg_lsn,
1111
OUT lsn pg_lsn,
12+
OUT blockid int2,
1213
OUT reltablespaceoid,
1314
OUT reldatabaseoid,
1415
OUT relfilenodeoid,
1516
OUT relblocknumber int8,
1617
OUT forknametext,
17-
OUT fpibytea
18+
OUT blockdatabytea,
19+
OUT fpibytea,
20+
OUT fpilen int4,
21+
OUT fpiinfotext[]
1822
)
1923
RETURNS SETOF record
20-
AS'MODULE_PATHNAME','pg_get_wal_fpi_info'
24+
AS'MODULE_PATHNAME','pg_get_wal_block_info'
2125
LANGUAGE C STRICT PARALLEL SAFE;
2226

23-
REVOKE EXECUTEON FUNCTIONpg_get_wal_fpi_info(pg_lsn, pg_lsn)FROM PUBLIC;
24-
GRANT EXECUTEON FUNCTIONpg_get_wal_fpi_info(pg_lsn, pg_lsn) TO pg_read_server_files;
27+
REVOKE EXECUTEON FUNCTIONpg_get_wal_block_info(pg_lsn, pg_lsn)FROM PUBLIC;
28+
GRANT EXECUTEON FUNCTIONpg_get_wal_block_info(pg_lsn, pg_lsn) TO pg_read_server_files;

‎contrib/pg_walinspect/pg_walinspect.c

Lines changed: 100 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include"access/xlogutils.h"
2121
#include"funcapi.h"
2222
#include"miscadmin.h"
23+
#include"utils/array.h"
2324
#include"utils/builtins.h"
2425
#include"utils/pg_lsn.h"
2526

@@ -30,7 +31,7 @@
3031

3132
PG_MODULE_MAGIC;
3233

33-
PG_FUNCTION_INFO_V1(pg_get_wal_fpi_info);
34+
PG_FUNCTION_INFO_V1(pg_get_wal_block_info);
3435
PG_FUNCTION_INFO_V1(pg_get_wal_record_info);
3536
PG_FUNCTION_INFO_V1(pg_get_wal_records_info);
3637
PG_FUNCTION_INFO_V1(pg_get_wal_records_info_till_end_of_wal);
@@ -56,7 +57,7 @@ static void FillXLogStatsRow(const char *name, uint64 n, uint64 total_count,
5657
Datum*values,bool*nulls,uint32ncols);
5758
staticvoidGetWalStats(FunctionCallInfofcinfo,XLogRecPtrstart_lsn,
5859
XLogRecPtrend_lsn,boolstats_per_record);
59-
staticvoidGetWALFPIInfo(FunctionCallInfofcinfo,XLogReaderState*record);
60+
staticvoidGetWALBlockInfo(FunctionCallInfofcinfo,XLogReaderState*record);
6061

6162
/*
6263
* Check if the given LSN is in future. Also, return the LSN up to which the
@@ -221,49 +222,40 @@ GetWALRecordInfo(XLogReaderState *record, Datum *values,
221222

222223

223224
/*
224-
* Store a set of full page images from a single record.
225+
* Store a set of block information from a single record (FPI and block
226+
* information).
225227
*/
226228
staticvoid
227-
GetWALFPIInfo(FunctionCallInfofcinfo,XLogReaderState*record)
229+
GetWALBlockInfo(FunctionCallInfofcinfo,XLogReaderState*record)
228230
{
229-
#definePG_GET_WAL_FPI_INFO_COLS 7
231+
#definePG_GET_WAL_BLOCK_INFO_COLS 11
230232
intblock_id;
231233
ReturnSetInfo*rsinfo= (ReturnSetInfo*)fcinfo->resultinfo;
232234

233235
for (block_id=0;block_id <=XLogRecMaxBlockId(record);block_id++)
234236
{
235-
PGAlignedBlockbuf;
236-
Pagepage;
237-
bytea*raw_page;
238-
BlockNumberblk;
237+
DecodedBkpBlock*blk;
238+
BlockNumberblkno;
239239
RelFileLocatorrnode;
240240
ForkNumberfork;
241-
Datumvalues[PG_GET_WAL_FPI_INFO_COLS]= {0};
242-
boolnulls[PG_GET_WAL_FPI_INFO_COLS]= {0};
241+
Datumvalues[PG_GET_WAL_BLOCK_INFO_COLS]= {0};
242+
boolnulls[PG_GET_WAL_BLOCK_INFO_COLS]= {0};
243243
inti=0;
244244

245245
if (!XLogRecHasBlockRef(record,block_id))
246246
continue;
247247

248-
if (!XLogRecHasBlockImage(record,block_id))
249-
continue;
250-
251-
page= (Page)buf.data;
252-
253-
if (!RestoreBlockImage(record,block_id,page))
254-
ereport(ERROR,
255-
(errcode(ERRCODE_INTERNAL_ERROR),
256-
errmsg_internal("%s",record->errormsg_buf)));
248+
blk=XLogRecGetBlock(record,block_id);
257249

258-
/* Full page exists, so let's save it. */
259250
(void)XLogRecGetBlockTagExtended(record,block_id,
260-
&rnode,&fork,&blk,NULL);
251+
&rnode,&fork,&blkno,NULL);
261252

262253
values[i++]=LSNGetDatum(record->ReadRecPtr);
263-
values[i++]=ObjectIdGetDatum(rnode.spcOid);
264-
values[i++]=ObjectIdGetDatum(rnode.dbOid);
265-
values[i++]=ObjectIdGetDatum(rnode.relNumber);
266-
values[i++]=Int64GetDatum((int64)blk);
254+
values[i++]=Int16GetDatum(block_id);
255+
values[i++]=ObjectIdGetDatum(blk->rlocator.spcOid);
256+
values[i++]=ObjectIdGetDatum(blk->rlocator.dbOid);
257+
values[i++]=ObjectIdGetDatum(blk->rlocator.relNumber);
258+
values[i++]=Int64GetDatum((int64)blkno);
267259

268260
if (fork >=0&&fork <=MAX_FORKNUM)
269261
values[i++]=CStringGetTextDatum(forkNames[fork]);
@@ -272,34 +264,102 @@ GetWALFPIInfo(FunctionCallInfo fcinfo, XLogReaderState *record)
272264
(errcode(ERRCODE_INTERNAL_ERROR),
273265
errmsg_internal("invalid fork number: %u",fork)));
274266

275-
/* Initialize bytea buffer to copy the FPI to. */
276-
raw_page= (bytea*)palloc(BLCKSZ+VARHDRSZ);
277-
SET_VARSIZE(raw_page,BLCKSZ+VARHDRSZ);
267+
/* Block data */
268+
if (blk->has_data)
269+
{
270+
bytea*raw_data;
271+
272+
/* Initialize bytea buffer to copy the data to */
273+
raw_data= (bytea*)palloc(blk->data_len+VARHDRSZ);
274+
SET_VARSIZE(raw_data,blk->data_len+VARHDRSZ);
278275

279-
/* Take a verbatim copy of the FPI. */
280-
memcpy(VARDATA(raw_page),page,BLCKSZ);
276+
/* Copy the data */
277+
memcpy(VARDATA(raw_data),blk->data,blk->data_len);
278+
values[i++]=PointerGetDatum(raw_data);
279+
}
280+
else
281+
{
282+
/* No data, so set this field to NULL */
283+
nulls[i++]= true;
284+
}
281285

282-
values[i++]=PointerGetDatum(raw_page);
286+
if (blk->has_image)
287+
{
288+
PGAlignedBlockbuf;
289+
Pagepage;
290+
bytea*raw_page;
291+
intbitcnt;
292+
intcnt=0;
293+
Datum*flags;
294+
ArrayType*a;
295+
296+
page= (Page)buf.data;
297+
298+
/* Full page image exists, so let's save it */
299+
if (!RestoreBlockImage(record,block_id,page))
300+
ereport(ERROR,
301+
(errcode(ERRCODE_INTERNAL_ERROR),
302+
errmsg_internal("%s",record->errormsg_buf)));
303+
304+
/* Initialize bytea buffer to copy the FPI to */
305+
raw_page= (bytea*)palloc(BLCKSZ+VARHDRSZ);
306+
SET_VARSIZE(raw_page,BLCKSZ+VARHDRSZ);
307+
308+
/* Take a verbatim copy of the FPI */
309+
memcpy(VARDATA(raw_page),page,BLCKSZ);
310+
311+
values[i++]=PointerGetDatum(raw_page);
312+
values[i++]=UInt32GetDatum(blk->bimg_len);
313+
314+
/* FPI flags */
315+
bitcnt=pg_popcount((constchar*)&blk->bimg_info,
316+
sizeof(uint8));
317+
/* Build set of raw flags */
318+
flags= (Datum*)palloc0(sizeof(Datum)*bitcnt);
319+
320+
if ((blk->bimg_info&BKPIMAGE_HAS_HOLE)!=0)
321+
flags[cnt++]=CStringGetTextDatum("HAS_HOLE");
322+
if (blk->apply_image)
323+
flags[cnt++]=CStringGetTextDatum("APPLY");
324+
if ((blk->bimg_info&BKPIMAGE_COMPRESS_PGLZ)!=0)
325+
flags[cnt++]=CStringGetTextDatum("COMPRESS_PGLZ");
326+
if ((blk->bimg_info&BKPIMAGE_COMPRESS_LZ4)!=0)
327+
flags[cnt++]=CStringGetTextDatum("COMPRESS_LZ4");
328+
if ((blk->bimg_info&BKPIMAGE_COMPRESS_ZSTD)!=0)
329+
flags[cnt++]=CStringGetTextDatum("COMPRESS_ZSTD");
330+
331+
Assert(cnt <=bitcnt);
332+
a=construct_array_builtin(flags,cnt,TEXTOID);
333+
values[i++]=PointerGetDatum(a);
334+
}
335+
else
336+
{
337+
/* No full page image, so store NULLs for all its fields */
338+
memset(&nulls[i], true,3*sizeof(bool));
339+
i+=3;
340+
}
283341

284-
Assert(i==PG_GET_WAL_FPI_INFO_COLS);
342+
Assert(i==PG_GET_WAL_BLOCK_INFO_COLS);
285343

286344
tuplestore_putvalues(rsinfo->setResult,rsinfo->setDesc,
287345
values,nulls);
288346
}
289347

290-
#undefPG_GET_WAL_FPI_INFO_COLS
348+
#undefPG_GET_WAL_FPI_BLOCK_COLS
291349
}
292350

293351
/*
294-
* Get full page images with their relation information for all the WAL
295-
* records between start and end LSNs. Decompression is applied to the
296-
* blocks, if necessary.
352+
* Get information about all the blocks saved in WAL records between start
353+
* and end LSNs. This produces information about the full page images with
354+
* their relation information, and the data saved in each block associated
355+
* to a record. Decompression is applied to the full page images, if
356+
* necessary.
297357
*
298358
* This function emits an error if a future start or end WAL LSN i.e. WAL LSN
299359
* the database system doesn't know about is specified.
300360
*/
301361
Datum
302-
pg_get_wal_fpi_info(PG_FUNCTION_ARGS)
362+
pg_get_wal_block_info(PG_FUNCTION_ARGS)
303363
{
304364
XLogRecPtrstart_lsn;
305365
XLogRecPtrend_lsn;
@@ -317,7 +377,7 @@ pg_get_wal_fpi_info(PG_FUNCTION_ARGS)
317377
xlogreader=InitXLogReaderState(start_lsn);
318378

319379
tmp_cxt=AllocSetContextCreate(CurrentMemoryContext,
320-
"pg_get_wal_fpi_info temporary cxt",
380+
"pg_get_block_fpi_info temporary cxt",
321381
ALLOCSET_DEFAULT_SIZES);
322382

323383
while (ReadNextXLogRecord(xlogreader)&&
@@ -326,7 +386,7 @@ pg_get_wal_fpi_info(PG_FUNCTION_ARGS)
326386
/* Use the tmp context so we can clean up after each tuple is done */
327387
old_cxt=MemoryContextSwitchTo(tmp_cxt);
328388

329-
GetWALFPIInfo(fcinfo,xlogreader);
389+
GetWALBlockInfo(fcinfo,xlogreader);
330390

331391
/* clean up and switch back */
332392
MemoryContextSwitchTo(old_cxt);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp