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

Commit127aea2

Browse files
committed
Add additional filtering options to pg_waldump.
Allow filtering by RelFileNode, BlockNumber, ForkNum and FPW.Author: David Christensen <david.christensen@crunchydata.com>Reviewed-by: Japin Li <japinli@hotmail.com>Reviewed-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>Reviewed-by: Cary Huang <cary.huang@highgo.ca>Reviewed-by: Thomas Munro <thomas.munro@gmail.com>Discussion:https://postgr.es/m/lzzgmgm6e5.fsf%40veeddrois.attlocal.net
1 parentac9c5dc commit127aea2

File tree

2 files changed

+192
-1
lines changed

2 files changed

+192
-1
lines changed

‎doc/src/sgml/ref/pg_waldump.sgml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,45 @@ PostgreSQL documentation
100100
</listitem>
101101
</varlistentry>
102102

103+
<varlistentry>
104+
<term><option>-k <replaceable>block</replaceable></option></term>
105+
<term><option>--block=<replaceable>block</replaceable></option></term>
106+
<listitem>
107+
<para>
108+
Only display records that modify the given block. The relation must
109+
also be provided with <option>--relation</option> or
110+
<option>-l</option>.
111+
</para>
112+
</listitem>
113+
</varlistentry>
114+
115+
<varlistentry>
116+
<term><option>-F <replaceable>fork</replaceable></option></term>
117+
<term><option>--fork=<replaceable>fork</replaceable></option></term>
118+
<listitem>
119+
<para>
120+
If provided, only display records that modify blocks in the given fork.
121+
The valid values are <literal>0</literal> for the main fork,
122+
<literal>1</literal> for the free space map,
123+
<literal>2</literal> for the visibility map,
124+
and <literal>3</literal> for the init fork.
125+
</para>
126+
</listitem>
127+
</varlistentry>
128+
129+
<varlistentry>
130+
<term><option>-l <replaceable>tblspc</replaceable>/<replaceable>db</replaceable>/<replaceable>rel</replaceable></option></term>
131+
<term><option>--relation=<replaceable>tblspc</replaceable>/<replaceable>db</replaceable>/<replaceable>rel</replaceable></option></term>
132+
<listitem>
133+
<para>
134+
Only display records that modify blocks in the given relation. The
135+
relation is specified with tablespace OID, database OID, and relfilenode
136+
separated by slashes, for example <literal>1234/12345/12345</literal>.
137+
This is the same format used for relations in the program's output.
138+
</para>
139+
</listitem>
140+
</varlistentry>
141+
103142
<varlistentry>
104143
<term><option>-n <replaceable>limit</replaceable></option></term>
105144
<term><option>--limit=<replaceable>limit</replaceable></option></term>
@@ -183,6 +222,16 @@ PostgreSQL documentation
183222
</listitem>
184223
</varlistentry>
185224

225+
<varlistentry>
226+
<term><option>-w</option></term>
227+
<term><option>--fullpage</option></term>
228+
<listitem>
229+
<para>
230+
Only display records that include full page images.
231+
</para>
232+
</listitem>
233+
</varlistentry>
234+
186235
<varlistentry>
187236
<term><option>-x <replaceable>xid</replaceable></option></term>
188237
<term><option>--xid=<replaceable>xid</replaceable></option></term>

‎src/bin/pg_waldump/pg_waldump.c

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static const char *progname;
3131
staticintWalSegSz;
3232
staticvolatilesig_atomic_ttime_to_stop= false;
3333

34+
staticconstRelFileNodeemptyRelFileNode= {0,0,0};
35+
3436
typedefstructXLogDumpPrivate
3537
{
3638
TimeLineIDtimeline;
@@ -55,6 +57,13 @@ typedef struct XLogDumpConfig
5557
boolfilter_by_rmgr_enabled;
5658
TransactionIdfilter_by_xid;
5759
boolfilter_by_xid_enabled;
60+
RelFileNodefilter_by_relation;
61+
boolfilter_by_extended;
62+
boolfilter_by_relation_enabled;
63+
BlockNumberfilter_by_relation_block;
64+
boolfilter_by_relation_block_enabled;
65+
ForkNumberfilter_by_relation_forknum;
66+
boolfilter_by_fpw;
5867
}XLogDumpConfig;
5968

6069
typedefstructStats
@@ -391,6 +400,59 @@ WALDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen,
391400
returncount;
392401
}
393402

403+
/*
404+
* Boolean to return whether the given WAL record matches a specific relation
405+
* and optionally block.
406+
*/
407+
staticbool
408+
XLogRecordMatchesRelationBlock(XLogReaderState*record,
409+
RelFileNodematchRnode,
410+
BlockNumbermatchBlock,
411+
ForkNumbermatchFork)
412+
{
413+
intblock_id;
414+
415+
for (block_id=0;block_id <=XLogRecMaxBlockId(record);block_id++)
416+
{
417+
RelFileNodernode;
418+
ForkNumberforknum;
419+
BlockNumberblk;
420+
421+
if (!XLogRecHasBlockRef(record,block_id))
422+
continue;
423+
424+
XLogRecGetBlockTag(record,block_id,&rnode,&forknum,&blk);
425+
426+
if ((matchFork==InvalidForkNumber||matchFork==forknum)&&
427+
(RelFileNodeEquals(matchRnode,emptyRelFileNode)||
428+
RelFileNodeEquals(matchRnode,rnode))&&
429+
(matchBlock==InvalidBlockNumber||matchBlock==blk))
430+
return true;
431+
}
432+
433+
return false;
434+
}
435+
436+
/*
437+
* Boolean to return whether the given WAL record contains a full page write.
438+
*/
439+
staticbool
440+
XLogRecordHasFPW(XLogReaderState*record)
441+
{
442+
intblock_id;
443+
444+
for (block_id=0;block_id <=XLogRecMaxBlockId(record);block_id++)
445+
{
446+
if (!XLogRecHasBlockRef(record,block_id))
447+
continue;
448+
449+
if (XLogRecHasBlockImage(record,block_id))
450+
return true;
451+
}
452+
453+
return false;
454+
}
455+
394456
/*
395457
* Calculate the size of a record, split into !FPI and FPI parts.
396458
*/
@@ -765,6 +827,10 @@ usage(void)
765827
printf(_(" -b, --bkp-details output detailed information about backup blocks\n"));
766828
printf(_(" -e, --end=RECPTR stop reading at WAL location RECPTR\n"));
767829
printf(_(" -f, --follow keep retrying after reaching end of WAL\n"));
830+
printf(_(" -k, --block=N with --relation, only show records matching this block\n"));
831+
printf(_(" -F, --fork=N only show records matching a specific fork number\n"
832+
" (defaults to showing all)\n"));
833+
printf(_(" -l, --relation=N/N/N only show records that affect a specific relation\n"));
768834
printf(_(" -n, --limit=N number of records to display\n"));
769835
printf(_(" -p, --path=PATH directory in which to find log segment files or a\n"
770836
" directory with a ./pg_wal that contains such files\n"
@@ -777,6 +843,7 @@ usage(void)
777843
" (default: 1 or the value used in STARTSEG)\n"));
778844
printf(_(" -V, --version output version information, then exit\n"));
779845
printf(_(" -x, --xid=XID only show records with transaction ID XID\n"));
846+
printf(_(" -w, --fullpage only show records with a full page write\n"));
780847
printf(_(" -z, --stats[=record] show statistics instead of records\n"
781848
" (optionally, show per-record statistics)\n"));
782849
printf(_(" -?, --help show this help, then exit\n"));
@@ -800,12 +867,16 @@ main(int argc, char **argv)
800867

801868
staticstructoptionlong_options[]= {
802869
{"bkp-details",no_argument,NULL,'b'},
870+
{"block",required_argument,NULL,'k'},
803871
{"end",required_argument,NULL,'e'},
804872
{"follow",no_argument,NULL,'f'},
873+
{"fork",required_argument,NULL,'F'},
874+
{"fullpage",no_argument,NULL,'w'},
805875
{"help",no_argument,NULL,'?'},
806876
{"limit",required_argument,NULL,'n'},
807877
{"path",required_argument,NULL,'p'},
808878
{"quiet",no_argument,NULL,'q'},
879+
{"relation",required_argument,NULL,'l'},
809880
{"rmgr",required_argument,NULL,'r'},
810881
{"start",required_argument,NULL,'s'},
811882
{"timeline",required_argument,NULL,'t'},
@@ -858,6 +929,11 @@ main(int argc, char **argv)
858929
config.filter_by_rmgr_enabled= false;
859930
config.filter_by_xid=InvalidTransactionId;
860931
config.filter_by_xid_enabled= false;
932+
config.filter_by_extended= false;
933+
config.filter_by_relation_enabled= false;
934+
config.filter_by_relation_block_enabled= false;
935+
config.filter_by_relation_forknum=InvalidForkNumber;
936+
config.filter_by_fpw= false;
861937
config.stats= false;
862938
config.stats_per_record= false;
863939

@@ -870,7 +946,7 @@ main(int argc, char **argv)
870946
gotobad_argument;
871947
}
872948

873-
while ((option=getopt_long(argc,argv,"be:fn:p:qr:s:t:x:z",
949+
while ((option=getopt_long(argc,argv,"be:fF:k:l:n:p:qr:s:t:wx:z",
874950
long_options,&optindex))!=-1)
875951
{
876952
switch (option)
@@ -890,6 +966,47 @@ main(int argc, char **argv)
890966
case'f':
891967
config.follow= true;
892968
break;
969+
case'F':
970+
{
971+
unsignedintforknum;
972+
973+
if (sscanf(optarg,"%u",&forknum)!=1||
974+
forknum>MAX_FORKNUM)
975+
{
976+
pg_log_error("could not parse valid fork number (0..%d) \"%s\"",
977+
MAX_FORKNUM,optarg);
978+
gotobad_argument;
979+
}
980+
config.filter_by_relation_forknum= (ForkNumber)forknum;
981+
config.filter_by_extended= true;
982+
}
983+
break;
984+
case'k':
985+
if (sscanf(optarg,"%u",&config.filter_by_relation_block)!=1||
986+
!BlockNumberIsValid(config.filter_by_relation_block))
987+
{
988+
pg_log_error("could not parse valid block number \"%s\"",optarg);
989+
gotobad_argument;
990+
}
991+
config.filter_by_relation_block_enabled= true;
992+
config.filter_by_extended= true;
993+
break;
994+
case'l':
995+
if (sscanf(optarg,"%u/%u/%u",
996+
&config.filter_by_relation.spcNode,
997+
&config.filter_by_relation.dbNode,
998+
&config.filter_by_relation.relNode)!=3||
999+
!OidIsValid(config.filter_by_relation.spcNode)||
1000+
!OidIsValid(config.filter_by_relation.relNode))
1001+
{
1002+
pg_log_error("could not parse valid relation from \"%s\""
1003+
" (expecting \"tablespace OID/database OID/"
1004+
"relation filenode\")",optarg);
1005+
gotobad_argument;
1006+
}
1007+
config.filter_by_relation_enabled= true;
1008+
config.filter_by_extended= true;
1009+
break;
8931010
case'n':
8941011
if (sscanf(optarg,"%d",&config.stop_after_records)!=1)
8951012
{
@@ -947,6 +1064,9 @@ main(int argc, char **argv)
9471064
gotobad_argument;
9481065
}
9491066
break;
1067+
case'w':
1068+
config.filter_by_fpw= true;
1069+
break;
9501070
case'x':
9511071
if (sscanf(optarg,"%u",&config.filter_by_xid)!=1)
9521072
{
@@ -976,6 +1096,13 @@ main(int argc, char **argv)
9761096
}
9771097
}
9781098

1099+
if (config.filter_by_relation_block_enabled&&
1100+
!config.filter_by_relation_enabled)
1101+
{
1102+
pg_log_error("--block option requires --relation option to be specified");
1103+
gotobad_argument;
1104+
}
1105+
9791106
if ((optind+2)<argc)
9801107
{
9811108
pg_log_error("too many command-line arguments (first is \"%s\")",
@@ -1148,6 +1275,21 @@ main(int argc, char **argv)
11481275
config.filter_by_xid!=record->xl_xid)
11491276
continue;
11501277

1278+
/* check for extended filtering */
1279+
if (config.filter_by_extended&&
1280+
!XLogRecordMatchesRelationBlock(xlogreader_state,
1281+
config.filter_by_relation_enabled ?
1282+
config.filter_by_relation :
1283+
emptyRelFileNode,
1284+
config.filter_by_relation_block_enabled ?
1285+
config.filter_by_relation_block :
1286+
InvalidBlockNumber,
1287+
config.filter_by_relation_forknum))
1288+
continue;
1289+
1290+
if (config.filter_by_fpw&& !XLogRecordHasFPW(xlogreader_state))
1291+
continue;
1292+
11511293
/* perform any per-record work */
11521294
if (!config.quiet)
11531295
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp