Skip to content

Commit b620f2d

Browse files
committed
Merge branch 'PGPROEE9_6_xlogdump_ts' into PGPROEE9_6
2 parents 2bd700b + 96e60c9 commit b620f2d

File tree

3 files changed

+202
-11
lines changed

3 files changed

+202
-11
lines changed

doc/src/sgml/ref/pg_xlogdump.sgml

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ doc/src/sgml/ref/pg_xlogdump.sgml
2323
<cmdsynopsis>
2424
<command>pg_xlogdump</command>
2525
<arg rep="repeat" choice="opt"><option>option</option></arg>
26+
<arg rep="repeat" choice="opt"><option>timestamp-option</option></arg>
2627
<arg choice="opt"><option>startseg</option>
2728
<arg choice="opt"><option>endseg</option></arg>
2829
</arg>
@@ -32,8 +33,8 @@ doc/src/sgml/ref/pg_xlogdump.sgml
3233
<refsect1 id="R1-APP-PGXLOGDUMP-1">
3334
<title>Description</title>
3435
<para>
35-
<command>pg_xlogdump</command> displays the write-ahead log (WAL) and is mainly
36-
useful for debugging or educational purposes.
36+
<command>pg_xlogdump</command> displays the write-ahead log (WAL) and prints timestamps for WAL records.
37+
This utility is mainly useful for debugging or educational purposes.
3738
</para>
3839

3940
<para>
@@ -55,7 +56,7 @@ doc/src/sgml/ref/pg_xlogdump.sgml
5556
<term><replaceable class="parameter">startseg</replaceable></term>
5657
<listitem>
5758
<para>
58-
Start reading at the specified log segment file. This implicitly determines
59+
Start reading at the specified log segment file. This implicitly determines
5960
the path in which files will be searched for, and the timeline to use.
6061
</para>
6162
</listitem>
@@ -117,9 +118,9 @@ doc/src/sgml/ref/pg_xlogdump.sgml
117118
<term><option>--path=<replaceable>path</replaceable></option></term>
118119
<listitem>
119120
<para>
120-
Specifies a directory to search for log segment files or a
121+
Specify a directory to search for log segment files or a
121122
directory with a <literal>pg_xlog</literal> subdirectory that
122-
contains such files. The default is to search in the current
123+
contains such files. The default is to search in the current
123124
directory, the <literal>pg_xlog</literal> subdirectory of the
124125
current directory, and the <literal>pg_xlog</literal> subdirectory
125126
of <envar>PGDATA</envar>.
@@ -132,9 +133,9 @@ doc/src/sgml/ref/pg_xlogdump.sgml
132133
<term><option>--rmgr=<replaceable>rmgr</replaceable></option></term>
133134
<listitem>
134135
<para>
135-
Only display records generated by the specified resource manager.
136-
If <literal>list</> is passed as name, print a list of valid resource manager
137-
names, and exit.
136+
Only display records generated by the specified <literal>rmgr</literal> resource manager.
137+
If you pass <literal>list</> as an argument, <application>pg_xlogdump</application> prints a list of valid resource manager
138+
names and exits.
138139
</para>
139140
</listitem>
140141
</varlistentry>
@@ -206,12 +207,71 @@ doc/src/sgml/ref/pg_xlogdump.sgml
206207
</varlistentry>
207208
</variablelist>
208209
</para>
210+
211+
<para>
212+
The following command-line options enable printing timestamps for various types of WAL records. You can use these options together with
213+
<replaceable class="parameter">startseg</replaceable>, <replaceable class="parameter">endseg</replaceable>, <option>-s</option>, and <option>-e</option> options.
214+
<variablelist>
215+
216+
<varlistentry>
217+
<term><option>-E</option></term>
218+
<listitem>
219+
<para>
220+
Print the timestamp of the last WAL record of the specified type found in the log segment file. When using this option, you must also specify the <option>-S</option> option.</para>
221+
<para>By default, <application>pg_xlogdump</application> prints timestamps only for COMMIT records. You can specify other record types using the <option>-F</option> option.
222+
</para>
223+
</listitem>
224+
</varlistentry>
225+
226+
<varlistentry>
227+
<term><option>-F</option> [<replaceable>argument1</replaceable>,<replaceable>argument2</replaceable>,...]</term>
228+
<listitem>
229+
<para>
230+
Specify WAL record types for which to print timestamps. When using this option, you must also specify the <option>-S</option> option.</para>
231+
<para>The <option>-F</option> option can take the following arguments, in the comma-separated format:</para>
232+
<itemizedlist>
233+
<listitem>
234+
<para><option>XLOG_RESTORE_POINT</option> &mdash; named restore points created with the <link linkend="functions-admin-backup">pg_create_restore_point()</link> function.</para>
235+
</listitem>
236+
<listitem>
237+
<para><option>XLOG_XACT_COMMIT</option> &mdash; commit records for transactions. These records are caused by the <xref linkend="sql-commit"> command.</para>
238+
</listitem>
239+
<listitem>
240+
<para><option>XLOG_XACT_COMMIT_PREPARED</option> &mdash; commit records for transactions that were earlier prepared for a two-phase commit. These records are caused by the <xref linkend="sql-commit-prepared"> command.</para>
241+
</listitem>
242+
<listitem>
243+
<para><option>XLOG_XACT_ABORT</option> &mdash; abort records for transactions. These records are caused by the <xref linkend="sql-rollback"> command.</para>
244+
</listitem>
245+
<listitem>
246+
<para><option>XLOG_XACT_ABORT_PREPARED</option> &mdash; abort records for transactions that were earlier prepared for a two-phase commit. These records are caused by the <xref linkend="sql-rollback-prepared"> command.</para>
247+
</listitem>
248+
</itemizedlist>
249+
<para>By default, <application>pg_xlogdump</application> prints timestamps only for COMMIT records.
250+
</para>
251+
</listitem>
252+
</varlistentry>
253+
254+
<varlistentry>
255+
<term><option>-S</option></term>
256+
<listitem>
257+
<para>
258+
Print the timestamp of the first WAL record of the specified type found in the log segment file. This option is required if you are going to use <option>-E</option> or <option>-F</option> options.</para>
259+
<para>By default, <application>pg_xlogdump</application> prints timestamps only for COMMIT records. You can specify other record types using the <option>-F</option> option.
260+
</para>
261+
</listitem>
262+
</varlistentry>
263+
264+
265+
</variablelist>
266+
</para>
267+
268+
209269
</refsect1>
210270

211271
<refsect1>
212272
<title>Notes</title>
213273
<para>
214-
Can give wrong results when the server is running.
274+
<application>pg_xlogdump</> can give wrong results when the server is running.
215275
</para>
216276

217277
<para>
@@ -221,8 +281,8 @@ doc/src/sgml/ref/pg_xlogdump.sgml
221281

222282
<para>
223283
<application>pg_xlogdump</> cannot read WAL files with suffix
224-
<literal>.partial</>. If those files need to be read, <literal>.partial</>
225-
suffix needs to be removed from the file name.
284+
<literal>.partial</>. If such files need to be read, <literal>.partial</>
285+
remove the suffix from the filename.
226286
</para>
227287
</refsect1>
228288

src/bin/pg_xlogdump/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ install: all installdirs
3333
installdirs:
3434
$(MKDIR_P) '$(DESTDIR)$(bindir)'
3535

36+
check:
37+
$(prove_check)
38+
3639
uninstall:
3740
rm -f '$(DESTDIR)$(bindir)/pg_xlogdump$(X)'
3841

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
use strict;
2+
use warnings;
3+
4+
use PostgresNode;
5+
use TestLib;
6+
use Test::More tests => 22;
7+
8+
# Test pg_xlogdump for timestamp output.
9+
10+
sub command_output
11+
{
12+
my ($cmd, $expected_stdout, $test_name) = @_;
13+
my ($stdout, $stderr);
14+
print("# Running: " . join(" ", @{$cmd}) . "\n");
15+
my $result = IPC::Run::run $cmd, '>', \$stdout, '2>', \$stderr;
16+
ok($result, "@$cmd exit code 0");
17+
is($stderr, '', "@$cmd no stderr");
18+
return $stdout;
19+
}
20+
21+
my $node = get_new_node('main');
22+
$node->init;
23+
$node->start;
24+
my $pgdata = $node->data_dir;
25+
my $xlogfilename0 = $node->safe_psql('postgres',
26+
"SELECT pg_xlogfile_name(pg_current_xlog_location())");
27+
my $startseg = "$pgdata/pg_xlog/$xlogfilename0";
28+
my $endseg = $startseg;
29+
$node->command_like(
30+
[ 'pg_xlogdump', '-S', "$pgdata/pg_xlog/$xlogfilename0" ],
31+
qr/pg_xlogdump: start timestamp:/,
32+
'pg_xlogdump prints start timestamp');
33+
$node->command_like(
34+
[ 'pg_xlogdump', '-S', "$pgdata/pg_xlog/$xlogfilename0" ],
35+
qr/start timestamp[^\n]*\n((?!end timestamp).)*$/m,
36+
'pg_xlogdump does not print end timestamp by default');
37+
$node->command_fails(
38+
[ 'pg_xlogdump', '-E', "$pgdata/pg_xlog/$xlogfilename0" ],
39+
'pg_xlogdump requires -S argument for printing start/end timestamps');
40+
$node->command_fails(
41+
[ 'pg_xlogdump', '-S', '-F', 'XXX', "$pgdata/pg_xlog/$xlogfilename0" ],
42+
'pg_xlogdump fails with invalid filter');
43+
$node->command_like(
44+
[ 'pg_xlogdump', '-S', '-F', 'XLOG_XACT_COMMIT,XLOG_XACT_ABORT', "$pgdata/pg_xlog/$xlogfilename0" ],
45+
qr/pg_xlogdump: start timestamp:/,
46+
'pg_xlogdump accepts filter "XLOG_XACT_COMMIT,XLOG_XACT_ABORT"');
47+
48+
open CONF, ">>$pgdata/postgresql.conf";
49+
print CONF "track_commit_timestamp = on\n";
50+
close CONF;
51+
$node->restart;
52+
53+
# create test tables and move to a new segment
54+
$node->safe_psql('postgres',
55+
"CREATE TABLE test1 (a int); CREATE TABLE test2 (a int); SELECT pg_switch_xlog()");
56+
57+
# get initial commit_timestamp and logfile_name
58+
$node->safe_psql('postgres',
59+
"INSERT INTO test1 VALUES (1)");
60+
my $tx1_timestamp = $node->safe_psql('postgres',
61+
"SELECT pg_xact_commit_timestamp(xmin) FROM test1"
62+
);
63+
print("# transaction 1 commit timestamp: $tx1_timestamp\n");
64+
my $xlogfilename1 = $node->safe_psql('postgres',
65+
"SELECT pg_xlogfile_name(pg_current_xlog_location())"
66+
);
67+
68+
# produce some xlog segments
69+
for (my $i = 0; $i < 10; $i++) {
70+
$node->safe_psql('postgres',
71+
"BEGIN; INSERT INTO test2 VALUES ($i); COMMIT; SELECT pg_switch_xlog()");
72+
}
73+
74+
# get a segment from the middle of the sequence
75+
my $xlogfilenameM = $node->safe_psql('postgres',
76+
"SELECT pg_xlogfile_name(pg_current_xlog_location())");
77+
78+
# produce last segment
79+
$node->safe_psql('postgres',
80+
"SELECT pg_sleep(2); DELETE FROM test2; INSERT INTO test2 VALUES (1)");
81+
82+
# insert XLOG_XACT_ABORT to make sure that the default bahaviour is to show only COMMIT TIMESTAMP
83+
$node->safe_psql('postgres',
84+
"SELECT pg_sleep(2); BEGIN TRANSACTION; DELETE FROM test2; ROLLBACK TRANSACTION");
85+
86+
# get final logfile_name and commit_timestamp (and switch segment)
87+
my $xlogfilenameN = $node->safe_psql('postgres',
88+
"SELECT pg_xlogfile_name(pg_current_xlog_location())");
89+
$node->safe_psql('postgres',
90+
"SELECT pg_switch_xlog()");
91+
my $tx2_timestamp = $node->safe_psql('postgres',
92+
"SELECT pg_xact_commit_timestamp(xmin) FROM test2"
93+
);
94+
print("# transaction N commit timestamp: $tx2_timestamp\n");
95+
96+
# remove a file from the middle to make sure that the modified pg_xlogdump reads only necessary files
97+
unlink "$pgdata/pg_xlog/$xlogfilenameM";
98+
99+
# run pg_xlogdump to check it's output
100+
my $xld_output = command_output(
101+
[ 'pg_xlogdump', '-S', '-E', "$pgdata/pg_xlog/$xlogfilename1", "$pgdata/pg_xlog/$xlogfilenameN" ]);
102+
ok($xld_output =~ qr/pg_xlogdump: start timestamp: ([^,]+), lsn: (.*)/, "start timestamp and lsn found");
103+
my ($startts, $startlsn) = ($1, $2);
104+
ok($xld_output =~ qr/pg_xlogdump: end timestamp: ([^,]+), lsn: (.*)/, "end timestamp and lsn found");
105+
106+
# check commit timestamps for first and last commits
107+
my ($endts, $endlsn) = ($1, $2);
108+
my $timediff1 = $node->safe_psql('postgres',
109+
"SELECT EXTRACT(EPOCH FROM pg_xact_commit_timestamp(xmin) - \'$startts\'::timestamp) FROM test1");
110+
ok($timediff1 >= 0 && $timediff1 < 1, "xlog start timestamp ($startts) equals to transaction 1 timestamp ($tx1_timestamp)");
111+
my $timediff2 = $node->safe_psql('postgres',
112+
"SELECT EXTRACT(EPOCH FROM \'$endts\'::timestamp - pg_xact_commit_timestamp(xmin)) FROM test2");
113+
ok($timediff2 >= 0 && $timediff2 < 1, "xlog end timestamp ($endts) equals to transaction N timestamp ($tx2_timestamp)");
114+
115+
# check lsns
116+
my $lsndiff1 = $node->safe_psql('postgres',
117+
"SELECT \'$endlsn\'::pg_lsn - \'$startlsn\'::pg_lsn");
118+
print("lsndiff1: $lsndiff1\n");
119+
ok($lsndiff1 > 0, "xlog end lsn ($endlsn) greater than xlog start lsn ($startlsn)");
120+
my $lsndiff2 = $node->safe_psql('postgres',
121+
"SELECT pg_current_xlog_location() - \'$endlsn\'::pg_lsn");
122+
ok($lsndiff2 >= 0, "xlog current lsn greater than or equal to xlog end lsn");
123+
124+
# check search for non-existing record types
125+
$node->command_like(
126+
[ 'pg_xlogdump', '-S', '-F', 'XLOG_RESTORE_POINT', "$pgdata/pg_xlog/$xlogfilename0" ],
127+
qr/xlog record with timestamp is not found/,
128+
'pg_xlogdump accepts filter XLOG_RESTORE_POINT and processes a segment without such records');

0 commit comments

Comments
 (0)