On Tue, Mar 30, 2021 at 11:00 AM Andres Freund <and...@anarazel.de> wrote:
>
> Hi,
>
> On 2021-03-30 10:13:29 +0530, vignesh C wrote:
> > On Tue, Mar 30, 2021 at 6:28 AM Andres Freund <and...@anarazel.de> wrote:
> > > Any chance you could write a tap test exercising a few of these cases?
> >
> > I can try to write a patch for this if nobody objects.
>
> Cool!
>

Attached a patch which has the test for the first scenario.

> > > E.g. things like:
> > >
> > > - create a few slots, drop one of them, shut down, start up, verify
> > >   stats are still sane
> > > - create a few slots, shut down, manually remove a slot, lower
> > >   max_replication_slots, start up
> >
> > Here by "manually remove a slot", do you mean to remove the slot
> > manually from the pg_replslot folder?
>
> Yep - thereby allowing max_replication_slots after the shutdown/start to
> be lower than the number of slots-stats objects.

I have not included the 2nd test in the patch as the test fails with
following warnings and also displays the statistics of the removed
slot:
WARNING:  problem in alloc set Statistics snapshot: detected write
past chunk end in block 0x55d038b8e410, chunk 0x55d038b8e438
WARNING:  problem in alloc set Statistics snapshot: detected write
past chunk end in block 0x55d038b8e410, chunk 0x55d038b8e438

This happens because the statistics file has an additional slot
present even though the replication slot was removed.  I felt this
issue should be fixed. I will try to fix this issue and send the
second test along with the fix.

Regards,
Vignesh
From c3aded40e0516dbd42d52c72c5b95ec45f991923 Mon Sep 17 00:00:00 2001
From: vignesh <vignes...@gmail.com>
Date: Wed, 31 Mar 2021 11:02:40 +0530
Subject: [PATCH v1] Added tests for verification of logical replication
 statistics.

Added tests for verification of logical replication statistics after
restart of server.
---
 src/test/subscription/t/022_repl_stats.pl | 161 ++++++++++++++++++++++
 1 file changed, 161 insertions(+)
 create mode 100644 src/test/subscription/t/022_repl_stats.pl

diff --git a/src/test/subscription/t/022_repl_stats.pl b/src/test/subscription/t/022_repl_stats.pl
new file mode 100644
index 0000000000..7755a447c0
--- /dev/null
+++ b/src/test/subscription/t/022_repl_stats.pl
@@ -0,0 +1,161 @@
+# Test replication statistics data gets updated in pg_stat_replication_slots
+# view for logical replication.
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More tests => 5;
+
+# Create publisher node.
+my $node_publisher = get_new_node('publisher');
+$node_publisher->init(allows_streaming => 'logical');
+$node_publisher->append_conf('postgresql.conf', 'logical_decoding_work_mem = 64kB');
+$node_publisher->start;
+
+# Create subscriber nodes.
+my $node_subscriber1 = get_new_node('subscriber1');
+$node_subscriber1->init(allows_streaming => 'logical');
+$node_subscriber1->start;
+
+my $node_subscriber2 = get_new_node('subscriber2');
+$node_subscriber2->init(allows_streaming => 'logical');
+$node_subscriber2->start;
+
+my $node_subscriber3 = get_new_node('subscriber3');
+$node_subscriber3->init(allows_streaming => 'logical');
+$node_subscriber3->start;
+
+# Create table on publisher.
+$node_publisher->safe_psql('postgres',
+        "CREATE TABLE test_tab (a int primary key, b varchar)");
+
+# Create table on subscribers.
+$node_subscriber1->safe_psql('postgres', "CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999)");
+$node_subscriber2->safe_psql('postgres', "CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999)");
+$node_subscriber3->safe_psql('postgres', "CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999)");
+
+# Setup logical replication.
+my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+$node_publisher->safe_psql('postgres', "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+
+my $appname1 = 'tap_sub1';
+$node_subscriber1->safe_psql('postgres',
+	"CREATE SUBSCRIPTION tap_sub1 
+	CONNECTION '$publisher_connstr 
+	application_name=$appname1' 
+	PUBLICATION tap_pub WITH (streaming = on)"
+);
+
+my $appname2 = 'tap_sub2';
+$node_subscriber2->safe_psql('postgres',
+	"CREATE SUBSCRIPTION tap_sub2
+	CONNECTION '$publisher_connstr
+	application_name=$appname2'
+	PUBLICATION tap_pub WITH (streaming = off)"
+);
+
+my $appname3 = 'tap_sub3';
+$node_subscriber3->safe_psql('postgres',
+	"CREATE SUBSCRIPTION tap_sub3
+	CONNECTION '$publisher_connstr
+	application_name=$appname3'
+	PUBLICATION tap_pub WITH (streaming = off)"
+);
+
+$node_publisher->wait_for_catchup($appname1);
+$node_publisher->wait_for_catchup($appname2);
+$node_publisher->wait_for_catchup($appname3);
+
+# Interleave a pair of transactions, each exceeding the 64kB limit.
+my $in  = '';
+my $out = '';
+
+my $timer = IPC::Run::timeout(180);
+
+my $h = $node_publisher->background_psql('postgres', \$in, \$out, $timer,
+        on_error_stop => 0);
+
+$in .= q{
+BEGIN;
+INSERT INTO test_tab SELECT i, md5(i::text) FROM generate_series(3, 5000) s(i);
+UPDATE test_tab SET b = md5(b) WHERE mod(a,2) = 0;
+DELETE FROM test_tab WHERE mod(a,3) = 0;
+};
+$h->pump_nb;
+
+$node_publisher->safe_psql(
+        'postgres', q{
+BEGIN;
+INSERT INTO test_tab SELECT i, md5(i::text) FROM generate_series(5001, 9999) s(i);
+DELETE FROM test_tab WHERE a > 5000;
+COMMIT;
+});
+
+$in .= q{
+COMMIT;
+\q
+};
+$h->finish;    # errors make the next test fail, so ignore them here
+
+$node_publisher->wait_for_catchup($appname1);
+$node_publisher->wait_for_catchup($appname2);
+$node_publisher->wait_for_catchup($appname3);
+
+# Verify data is replicated to the subscribers.
+my $result =
+  $node_subscriber1->safe_psql('postgres', "SELECT count(*), count(c), count(d = 999) FROM test_tab");
+is($result, qq(3332|3332|3332), 'check publisher data is replicated to the subscriber');
+
+$result =
+  $node_subscriber2->safe_psql('postgres', "SELECT count(*), count(c), count(d = 999) FROM test_tab");
+is($result, qq(3332|3332|3332), 'check publisher data is replicated to the subscriber');
+
+$result =
+  $node_subscriber3->safe_psql('postgres', "SELECT count(*), count(c), count(d = 999) FROM test_tab");
+is($result, qq(3332|3332|3332), 'check publisher data is replicated to the subscriber');
+
+# Test to verify replication statistics data is updated in
+# pg_stat_replication_slots statistics view.
+$result = $node_publisher->safe_psql('postgres', 
+	"SELECT slot_name,
+		spill_txns > 0 AS spill_txns,
+		spill_count > 0 AS spill_count,
+		spill_bytes > 0 AS spill_bytes,
+		stream_txns > 0 AS stream_txns,
+		stream_count > 0 AS stream_count,
+		stream_bytes > 0 AS stream_bytes,
+		stats_reset
+	FROM pg_stat_replication_slots ORDER BY slot_name"
+);
+is($result, qq(tap_sub1|f|f|f|t|t|t|
+tap_sub2|t|t|t|f|f|f|
+tap_sub3|t|t|t|f|f|f|), 'check replication statistics are updated');
+
+# Test to drop one of the subscribers and verify replication statistics data is
+# fine after publisher is restarted.
+$node_subscriber3->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub3;");
+
+$node_publisher->stop;
+$node_publisher->start;
+
+# Verify statistics data present in pg_stat_replication_slots are sane after
+# publisher is restarted
+$result = $node_publisher->safe_psql('postgres',
+        "SELECT slot_name,
+                spill_txns > 0 AS spill_txns,
+                spill_count > 0 AS spill_count,
+                spill_bytes > 0 AS spill_bytes,
+                stream_txns > 0 AS stream_txns,
+                stream_count > 0 AS stream_count,
+                stream_bytes > 0 AS stream_bytes,
+                stats_reset
+        FROM pg_stat_replication_slots ORDER BY slot_name"
+);
+is($result, qq(tap_sub1|f|f|f|t|t|t|
+tap_sub2|t|t|t|f|f|f|), 'check replication statistics are updated');
+
+# shutdown
+$node_subscriber1->stop;
+$node_subscriber2->stop;
+$node_subscriber3->stop;
+$node_publisher->stop;
-- 
2.25.1

Reply via email to