public inbox for [email protected]
help / color / mirror / Atom feed[PATCH 1/4] Add pg_am_size(), pg_namespace_size() ..
105+ messages / 14 participants
[nested] [flat]
* [PATCH 1/4] Add pg_am_size(), pg_namespace_size() ..
@ 2021-07-14 02:25 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: Justin Pryzby @ 2021-07-14 02:25 UTC (permalink / raw)
See also: 358a897fa, 528ac10c7
---
src/backend/utils/adt/dbsize.c | 130 ++++++++++++++++++++++++++++++++
src/include/catalog/pg_proc.dat | 19 +++++
2 files changed, 149 insertions(+)
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index b4a2c8d2197..a1348083ba3 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -13,18 +13,23 @@
#include <sys/stat.h>
+#include "access/genam.h"
#include "access/htup_details.h"
#include "access/relation.h"
+#include "access/table.h"
#include "catalog/catalog.h"
#include "catalog/namespace.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_tablespace.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/tablespace.h"
#include "miscadmin.h"
#include "storage/fd.h"
#include "utils/acl.h"
#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
#include "utils/numeric.h"
#include "utils/rel.h"
#include "utils/relfilenodemap.h"
@@ -832,6 +837,131 @@ pg_size_bytes(PG_FUNCTION_ARGS)
PG_RETURN_INT64(result);
}
+/*
+ * Return the sum of size of relations for which the given attribute of
+ * pg_class matches the specified OID value.
+ */
+static int64
+calculate_size_attvalue(int attnum, Oid attval)
+{
+ int64 totalsize = 0;
+ ScanKeyData skey;
+ Relation pg_class;
+ SysScanDesc scan;
+ HeapTuple tuple;
+
+ ScanKeyInit(&skey, attnum,
+ BTEqualStrategyNumber, F_OIDEQ, attval);
+
+ pg_class = table_open(RelationRelationId, AccessShareLock);
+ scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey);
+ while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+ {
+ Relation rel;
+ Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
+
+ rel = try_relation_open(classtuple->oid, AccessShareLock);
+ if (!rel)
+ continue;
+
+ for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
+ totalsize += calculate_relation_size(&rel->rd_node, rel->rd_backend, forkNum);
+
+ relation_close(rel, AccessShareLock);
+ }
+
+ systable_endscan(scan);
+ table_close(pg_class, AccessShareLock);
+ return totalsize;
+}
+
+/* Compute the size of relations in a schema (namespace) */
+static int64
+calculate_namespace_size(Oid nspOid)
+{
+ /*
+ * User must be a member of pg_read_all_stats or have CREATE privilege for
+ * target namespace.
+ */
+ if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
+ {
+ AclResult aclresult;
+ aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, OBJECT_SCHEMA,
+ get_namespace_name(nspOid));
+ }
+
+ return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid);
+}
+
+Datum
+pg_namespace_size_oid(PG_FUNCTION_ARGS)
+{
+ int64 size;
+ Oid nspOid = PG_GETARG_OID(0);
+
+ size = calculate_namespace_size(nspOid);
+
+ if (size < 0)
+ PG_RETURN_NULL();
+
+ PG_RETURN_INT64(size);
+}
+
+Datum
+pg_namespace_size_name(PG_FUNCTION_ARGS)
+{
+ int64 size;
+ Name nspName = PG_GETARG_NAME(0);
+ Oid nspOid = get_namespace_oid(NameStr(*nspName), false);
+
+ size = calculate_namespace_size(nspOid);
+
+ if (size < 0)
+ PG_RETURN_NULL();
+
+ PG_RETURN_INT64(size);
+}
+
+/* Compute the size of relations using the given access method */
+static int64
+calculate_am_size(Oid amOid)
+{
+ /* XXX acl_check? */
+
+ return calculate_size_attvalue(Anum_pg_class_relam, amOid);
+}
+
+Datum
+pg_am_size_oid(PG_FUNCTION_ARGS)
+{
+ int64 size;
+ Oid amOid = PG_GETARG_OID(0);
+
+ size = calculate_am_size(amOid);
+
+ if (size < 0)
+ PG_RETURN_NULL();
+
+ PG_RETURN_INT64(size);
+}
+
+Datum
+pg_am_size_name(PG_FUNCTION_ARGS)
+{
+ int64 size;
+ Name amName = PG_GETARG_NAME(0);
+ Oid amOid = get_am_oid(NameStr(*amName), false);
+
+ size = calculate_am_size(amOid);
+
+ if (size < 0)
+ PG_RETURN_NULL();
+
+ PG_RETURN_INT64(size);
+}
+
/*
* Get the filenode of a relation
*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 87aa571a331..7507193f85d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -7281,6 +7281,25 @@
descr => 'total disk space usage for the specified tablespace',
proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8',
proargtypes => 'name', prosrc => 'pg_tablespace_size_name' },
+
+{ oid => '9410',
+ descr => 'total disk space usage for the specified namespace',
+ proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' },
+{ oid => '9411',
+ descr => 'total disk space usage for the specified namespace',
+ proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'name', prosrc => 'pg_namespace_size_name' },
+
+{ oid => '9412',
+ descr => 'total disk space usage for the specified access method',
+ proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'oid', prosrc => 'pg_am_size_oid' },
+{ oid => '9413',
+ descr => 'total disk space usage for the specified access method',
+ proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'name', prosrc => 'pg_am_size_name' },
+
{ oid => '2324', descr => 'total disk space usage for the specified database',
proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8',
proargtypes => 'oid', prosrc => 'pg_database_size_oid' },
--
2.17.1
--HcAYCG3uE/tztfnV
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="0002-psql-add-convenience-commands-dA-and-dn.patch"
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
@ 2023-01-09 08:51 Amit Kapila <[email protected]>
2023-01-09 09:32 ` RE: Perform streaming logical transactions by background workers and parallel apply Shinoda, Noriyoshi (PN Japan FSIP) <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-10 05:46 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
2023-01-15 17:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 5 replies; 105+ messages in thread
From: Amit Kapila @ 2023-01-09 08:51 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Sun, Jan 8, 2023 at 11:32 AM [email protected]
<[email protected]> wrote:
>
> On Sunday, January 8, 2023 11:59 AM [email protected] <[email protected]> wrote:
> > Attach the updated patch set.
>
> Sorry, the commit message of 0001 was accidentally deleted, just attach
> the same patch set again with commit message.
>
Pushed the first (0001) patch.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-09 09:32 ` Shinoda, Noriyoshi (PN Japan FSIP) <[email protected]>
2023-01-09 10:15 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
4 siblings, 1 reply; 105+ messages in thread
From: Shinoda, Noriyoshi (PN Japan FSIP) @ 2023-01-09 09:32 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; [email protected] <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
Hi, Thanks for the great new feature.
Applied patches include adding wait events LogicalParallelApplyMain, LogicalParallelApplyStateChange.
However, it seems that monitoring.sgml only contains descriptions for pg_locks. The attached patch adds relevant wait event information.
Please update if you have a better description.
Noriyoshi Shinoda
-----Original Message-----
From: Amit Kapila <[email protected]>
Sent: Monday, January 9, 2023 5:51 PM
To: [email protected]
Cc: Masahiko Sawada <[email protected]>; [email protected]; Peter Smith <[email protected]>; [email protected]; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
Subject: Re: Perform streaming logical transactions by background workers and parallel apply
On Sun, Jan 8, 2023 at 11:32 AM [email protected] <[email protected]> wrote:
>
> On Sunday, January 8, 2023 11:59 AM [email protected] <[email protected]> wrote:
> > Attach the updated patch set.
>
> Sorry, the commit message of 0001 was accidentally deleted, just
> attach the same patch set again with commit message.
>
Pushed the first (0001) patch.
--
With Regards,
Amit Kapila.
Attachments:
[application/octet-stream] monitoring_wait_event_v1.diff (967B, ../../DM4PR84MB173460530245F56364E1DAF7EEFE9@DM4PR84MB1734.NAMPRD84.PROD.OUTLOOK.COM/2-monitoring_wait_event_v1.diff)
download | inline diff:
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index cf220c3bcb..f5d37f71d8 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1131,6 +1131,14 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<entry><literal>LogicalLauncherMain</literal></entry>
<entry>Waiting in main loop of logical replication launcher process.</entry>
</row>
+ <row>
+ <entry><literal>LogicalParallelApplyMain</literal></entry>
+ <entry>Waiting in main loop of logical replication parallel apply process.</entry>
+ </row>
+ <row>
+ <entry><literal>LogicalParallelApplyStateChange</literal></entry>
+ <entry>Waiting in main loop of logical replication parallel apply status change.</entry>
+ </row>
<row>
<entry><literal>RecoveryWalStream</literal></entry>
<entry>Waiting in main loop of startup process for WAL to arrive, during
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-09 09:32 ` RE: Perform streaming logical transactions by background workers and parallel apply Shinoda, Noriyoshi (PN Japan FSIP) <[email protected]>
@ 2023-01-09 10:15 ` [email protected] <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: [email protected] @ 2023-01-09 10:15 UTC (permalink / raw)
To: Shinoda, Noriyoshi (PN Japan FSIP) <[email protected]>; Amit Kapila <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Monday, January 9, 2023 5:32 PM Shinoda, Noriyoshi (PN Japan FSIP) <[email protected]> wrote:
>
> Hi, Thanks for the great new feature.
>
> Applied patches include adding wait events LogicalParallelApplyMain,
> LogicalParallelApplyStateChange.
> However, it seems that monitoring.sgml only contains descriptions for
> pg_locks. The attached patch adds relevant wait event information.
> Please update if you have a better description.
Thanks for reporting. I think for LogicalParallelApplyStateChange we'd better
document it in a consistent style with LogicalSyncStateChange, so I have
slightly adjusted the patch for the same.
Best regards,
Hou zj
Attachments:
[application/octet-stream] v2-0001-document-the-newly-added-wait-event.patch (1.6K, ../../OS0PR01MB57160F7022271D42DB0C965794FE9@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v2-0001-document-the-newly-added-wait-event.patch)
download | inline diff:
From bbcd2134982e818f5b4e816e9cd82eb1f79c43d8 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Mon, 9 Jan 2023 18:05:30 +0800
Subject: [PATCH] document the newly added wait event
Author: Shinoda, Noriyoshi
---
doc/src/sgml/monitoring.sgml | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index cf220c3..358d2ff 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1132,6 +1132,11 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<entry>Waiting in main loop of logical replication launcher process.</entry>
</row>
<row>
+ <entry><literal>LogicalParallelApplyMain</literal></entry>
+ <entry>Waiting in main loop of logical replication parallel apply
+ process.</entry>
+ </row>
+ <row>
<entry><literal>RecoveryWalStream</literal></entry>
<entry>Waiting in main loop of startup process for WAL to arrive, during
streaming recovery.</entry>
@@ -1728,6 +1733,11 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
tuples into new buckets.</entry>
</row>
<row>
+ <entry><literal>LogicalParallelApplyStateChange</literal></entry>
+ <entry>Waiting for a logical replication parallel apply process to change
+ state.</entry>
+ </row>
+ <row>
<entry><literal>LogicalSyncData</literal></entry>
<entry>Waiting for a logical replication remote server to send data for
initial table synchronization.</entry>
--
2.7.2.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-10 04:55 ` [email protected] <[email protected]>
2023-01-10 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Dilip Kumar <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
4 siblings, 2 replies; 105+ messages in thread
From: [email protected] @ 2023-01-10 04:55 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Monday, January 9, 2023 4:51 PM Amit Kapila <[email protected]> wrote:
>
> On Sun, Jan 8, 2023 at 11:32 AM [email protected]
> <[email protected]> wrote:
> >
> > On Sunday, January 8, 2023 11:59 AM [email protected]
> <[email protected]> wrote:
> > > Attach the updated patch set.
> >
> > Sorry, the commit message of 0001 was accidentally deleted, just
> > attach the same patch set again with commit message.
> >
>
> Pushed the first (0001) patch.
Thanks for pushing, here are the remaining patches.
I reordered the patch number to put patches that are easier to
commit in the front of others.
Best regards,
Hou zj
Attachments:
[application/octet-stream] v78-0004-Retry-to-apply-streaming-xact-only-in-apply-work.patch (21.1K, ../../OS0PR01MB5716863B23DBAD186F64ADF194FF9@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v78-0004-Retry-to-apply-streaming-xact-only-in-apply-work.patch)
download | inline diff:
From c1cfd9f8ed4fcc162367a6185a29f7639d151fa8 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Sun, 11 Dec 2022 19:16:34 +0800
Subject: [PATCH v78 4/4] Retry to apply streaming xact only in apply worker
When the subscription parameter is set streaming=parallel, the logic tries to
apply the streaming transaction using a parallel apply worker. If this
fails the parallel worker exits with an error.
In this case, retry applying the streaming transaction using the normal
streaming=on mode. This is done to avoid getting caught in a loop of the same
retry errors.
A new flag field "subretry" has been introduced to catalog "pg_subscription".
If there are any active parallel apply workers and the subscriber exits with an
error, this flag will be set true, and whenever the transaction is applied
successfully, this flag is reset false.
Now, when deciding how to apply a streaming transaction, the logic can know if
this transaction has previously failed or not (by checking the "subretry"
field).
Note: Since we add a new field 'subretry' to catalog 'pg_subscription' has been
expanded, we need bump catalog version.
---
doc/src/sgml/catalogs.sgml | 10 ++
doc/src/sgml/logical-replication.sgml | 11 +-
doc/src/sgml/ref/create_subscription.sgml | 5 +
src/backend/catalog/pg_subscription.c | 1 +
src/backend/catalog/system_views.sql | 2 +-
src/backend/commands/subscriptioncmds.c | 1 +
.../replication/logical/applyparallelworker.c | 30 ++++
src/backend/replication/logical/worker.c | 182 +++++++++++++++------
src/bin/pg_dump/pg_dump.c | 5 +-
src/include/catalog/pg_subscription.h | 7 +
src/include/replication/worker_internal.h | 2 +
src/test/subscription/t/015_stream.pl | 63 +++++++
12 files changed, 263 insertions(+), 56 deletions(-)
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index c1e4048..d918327 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -7950,6 +7950,16 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l
<row>
<entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>subretry</structfield> <type>bool</type>
+ </para>
+ <para>
+ True if previous change failed to be applied while there were any
+ active parallel apply workers, necessitating a retry.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
<structfield>subconninfo</structfield> <type>text</type>
</para>
<para>
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 8029fab..6254388 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1504,12 +1504,11 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
<para>
When the streaming mode is <literal>parallel</literal>, the finish LSN of
- failed transactions may not be logged. In that case, it may be necessary to
- change the streaming mode to <literal>on</literal> or <literal>off</literal> and
- cause the same conflicts again so the finish LSN of the failed transaction will
- be written to the server log. For the usage of finish LSN, please refer to <link
- linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION ...
- SKIP</command></link>.
+ failed transactions may not be logged. In that case, the failed transaction
+ will be retried in <literal>streaming = on</literal> mode. If it fails
+ again, the finish LSN of the failed transaction will be written to the
+ server log. For the usage of finish LSN, please refer to
+ <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION ... SKIP</command></link>.
</para>
</sect1>
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
index eba72c6..decd554 100644
--- a/doc/src/sgml/ref/create_subscription.sgml
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -251,6 +251,11 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
transaction is committed. Note that if an error happens in a
parallel apply worker, the finish LSN of the remote transaction
might not be reported in the server log.
+ When applying streaming transactions, if a deadlock is detected, the
+ parallel apply worker will exit with an error. The
+ <literal>parallel</literal> mode is disregarded when retrying;
+ instead the transaction will be applied using <literal>on</literal>
+ mode.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index a56ae31..0eb5ffb 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -71,6 +71,7 @@ GetSubscription(Oid subid, bool missing_ok)
sub->stream = subform->substream;
sub->twophasestate = subform->subtwophasestate;
sub->disableonerr = subform->subdisableonerr;
+ sub->retry = subform->subretry;
/* Get conninfo */
datum = SysCacheGetAttr(SUBSCRIPTIONOID,
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 72e46e5..aef926a 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1302,7 +1302,7 @@ REVOKE ALL ON pg_replication_origin_status FROM public;
REVOKE ALL ON pg_subscription FROM public;
GRANT SELECT (oid, subdbid, subskiplsn, subname, subowner, subenabled,
subbinary, substream, subtwophasestate, subdisableonerr,
- subslotname, subsynccommit, subpublications, suborigin)
+ subretry, subslotname, subsynccommit, subpublications, suborigin)
ON pg_subscription TO public;
CREATE VIEW pg_stat_subscription_stats AS
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index baff00d..b2053f7 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -636,6 +636,7 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
LOGICALREP_TWOPHASE_STATE_PENDING :
LOGICALREP_TWOPHASE_STATE_DISABLED);
values[Anum_pg_subscription_subdisableonerr - 1] = BoolGetDatum(opts.disableonerr);
+ values[Anum_pg_subscription_subretry - 1] = BoolGetDatum(false);
values[Anum_pg_subscription_subconninfo - 1] =
CStringGetTextDatum(conninfo);
if (opts.slot_name)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index a7ce57b..e14785a 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -315,6 +315,17 @@ pa_can_start(void)
if (!AllTablesyncsReady())
return false;
+ /*
+ * Don't use parallel apply workers for retries, because it is possible
+ * that a deadlock was detected the last time we tried to apply a
+ * transaction using a parallel apply worker.
+ */
+ if (MySubscription->retry)
+ {
+ elog(DEBUG1, "parallel apply workers are not used for retries");
+ return false;
+ }
+
return true;
}
@@ -1678,3 +1689,22 @@ pa_xact_finish(ParallelApplyWorkerInfo *winfo, XLogRecPtr remote_lsn)
pa_free_worker(winfo);
}
+
+/* Check if any active parallel apply workers. */
+bool
+pa_have_active_worker(void)
+{
+ ListCell *lc;
+
+ foreach(lc, ParallelApplyWorkerPool)
+ {
+ ParallelApplyWorkerInfo *tmp_winfo;
+
+ tmp_winfo = (ParallelApplyWorkerInfo *) lfirst(lc);
+
+ if (tmp_winfo->in_use)
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 5c8ce97..0c7bf67 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -394,7 +394,7 @@ static void stream_close_file(void);
static void send_feedback(XLogRecPtr recvpos, bool force, bool requestReply);
-static void DisableSubscriptionAndExit(void);
+static void DisableSubscriptionOnError(void);
static void apply_handle_commit_internal(LogicalRepCommitData *commit_data);
static void apply_handle_insert_internal(ApplyExecutionData *edata,
@@ -431,6 +431,8 @@ static inline void reset_apply_error_context_info(void);
static TransApplyAction get_transaction_apply_action(TransactionId xid,
ParallelApplyWorkerInfo **winfo);
+static void set_subscription_retry(bool retry);
+
/*
* Return the name of the logical replication worker.
*/
@@ -1046,6 +1048,9 @@ apply_handle_commit(StringInfo s)
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(commit_data.end_lsn);
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_activity(STATE_IDLE, NULL);
reset_apply_error_context_info();
}
@@ -1152,6 +1157,9 @@ apply_handle_prepare(StringInfo s)
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(prepare_data.end_lsn);
@@ -1208,6 +1216,9 @@ apply_handle_commit_prepared(StringInfo s)
store_flush_position(prepare_data.end_lsn, XactLastCommitEnd);
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(prepare_data.end_lsn);
@@ -1269,6 +1280,9 @@ apply_handle_rollback_prepared(StringInfo s)
store_flush_position(rollback_data.rollback_end_lsn, XactLastCommitEnd);
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(rollback_data.rollback_end_lsn);
@@ -1394,6 +1408,9 @@ apply_handle_stream_prepare(StringInfo s)
break;
}
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_stat(false);
/* Process any tables that are being synchronized in parallel. */
@@ -1970,6 +1987,10 @@ apply_handle_stream_abort(StringInfo s)
break;
}
+ /* Reset the retry flag. */
+ if (toplevel_xact)
+ set_subscription_retry(false);
+
reset_apply_error_context_info();
}
@@ -2252,6 +2273,9 @@ apply_handle_stream_commit(StringInfo s)
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(commit_data.end_lsn);
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_activity(STATE_IDLE, NULL);
reset_apply_error_context_info();
@@ -4348,20 +4372,28 @@ start_table_sync(XLogRecPtr *origin_startpos, char **myslotname)
}
PG_CATCH();
{
+ /*
+ * Emit the error message, and recover from the error state to an idle
+ * state
+ */
+ HOLD_INTERRUPTS();
+
+ EmitErrorReport();
+ AbortOutOfAnyTransaction();
+ FlushErrorState();
+
+ RESUME_INTERRUPTS();
+
+ /* Report the worker failed during table synchronization */
+ pgstat_report_subscription_error(MySubscription->oid, false);
+
if (MySubscription->disableonerr)
- DisableSubscriptionAndExit();
- else
- {
- /*
- * Report the worker failed during table synchronization. Abort
- * the current transaction so that the stats message is sent in an
- * idle state.
- */
- AbortOutOfAnyTransaction();
- pgstat_report_subscription_error(MySubscription->oid, false);
+ DisableSubscriptionOnError();
- PG_RE_THROW();
- }
+ /* Set the retry flag. */
+ set_subscription_retry(true);
+
+ proc_exit(0);
}
PG_END_TRY();
@@ -4386,20 +4418,27 @@ start_apply(XLogRecPtr origin_startpos)
}
PG_CATCH();
{
+ /*
+ * Emit the error message, and recover from the error state to an idle
+ * state
+ */
+ HOLD_INTERRUPTS();
+
+ EmitErrorReport();
+ AbortOutOfAnyTransaction();
+ FlushErrorState();
+
+ RESUME_INTERRUPTS();
+
+ /* Report the worker failed while applying changes */
+ pgstat_report_subscription_error(MySubscription->oid,
+ !am_tablesync_worker());
+
if (MySubscription->disableonerr)
- DisableSubscriptionAndExit();
- else
- {
- /*
- * Report the worker failed while applying changes. Abort the
- * current transaction so that the stats message is sent in an
- * idle state.
- */
- AbortOutOfAnyTransaction();
- pgstat_report_subscription_error(MySubscription->oid, !am_tablesync_worker());
+ DisableSubscriptionOnError();
- PG_RE_THROW();
- }
+ /* Set the retry flag. */
+ set_subscription_retry(true);
}
PG_END_TRY();
}
@@ -4675,39 +4714,20 @@ ApplyWorkerMain(Datum main_arg)
}
/*
- * After error recovery, disable the subscription in a new transaction
- * and exit cleanly.
+ * Disable the subscription in a new transaction.
*/
static void
-DisableSubscriptionAndExit(void)
+DisableSubscriptionOnError(void)
{
- /*
- * Emit the error message, and recover from the error state to an idle
- * state
- */
- HOLD_INTERRUPTS();
-
- EmitErrorReport();
- AbortOutOfAnyTransaction();
- FlushErrorState();
-
- RESUME_INTERRUPTS();
-
- /* Report the worker failed during either table synchronization or apply */
- pgstat_report_subscription_error(MyLogicalRepWorker->subid,
- !am_tablesync_worker());
-
/* Disable the subscription */
StartTransactionCommand();
DisableSubscription(MySubscription->oid);
CommitTransactionCommand();
- /* Notify the subscription has been disabled and exit */
+ /* Notify the subscription has been disabled */
ereport(LOG,
errmsg("subscription \"%s\" has been disabled because of an error",
MySubscription->name));
-
- proc_exit(0);
}
/*
@@ -5050,3 +5070,71 @@ get_transaction_apply_action(TransactionId xid, ParallelApplyWorkerInfo **winfo)
return TRANS_LEADER_SEND_TO_PARALLEL;
}
}
+
+/*
+ * Set subretry of pg_subscription catalog.
+ *
+ * If retry is true, subscriber is about to exit with an error. Otherwise, it
+ * means that the transaction was applied successfully.
+ */
+static void
+set_subscription_retry(bool retry)
+{
+ Relation rel;
+ HeapTuple tup;
+ bool started_tx = false;
+ bool nulls[Natts_pg_subscription];
+ bool replaces[Natts_pg_subscription];
+ Datum values[Natts_pg_subscription];
+
+ /* Fast path - if no state change then nothing to do */
+ if (MySubscription->retry == retry)
+ return;
+
+ /* Fast path - skip for parallel apply workers */
+ if (am_parallel_apply_worker())
+ return;
+
+ /* Fast path - skip set retry if no active parallel apply workers */
+ if (retry && !pa_have_active_worker())
+ return;
+
+ if (!IsTransactionState())
+ {
+ StartTransactionCommand();
+ started_tx = true;
+ }
+
+ /* Look up the subscription in the catalog */
+ rel = table_open(SubscriptionRelationId, RowExclusiveLock);
+ tup = SearchSysCacheCopy1(SUBSCRIPTIONOID,
+ ObjectIdGetDatum(MySubscription->oid));
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "subscription \"%s\" does not exist", MySubscription->name);
+
+ LockSharedObject(SubscriptionRelationId, MySubscription->oid, 0,
+ AccessShareLock);
+
+ /* Form a new tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ /* Set subretry */
+ values[Anum_pg_subscription_subretry - 1] = BoolGetDatum(retry);
+ replaces[Anum_pg_subscription_subretry - 1] = true;
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
+ replaces);
+
+ /* Update the catalog. */
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ /* Cleanup. */
+ heap_freetuple(tup);
+ table_close(rel, NoLock);
+
+ if (started_tx)
+ CommitTransactionCommand();
+}
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 5e800dc..931233f 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -4560,8 +4560,9 @@ getSubscriptions(Archive *fout)
ntups = PQntuples(res);
/*
- * Get subscription fields. We don't include subskiplsn in the dump as
- * after restoring the dump this value may no longer be relevant.
+ * Get subscription fields. We don't include subskiplsn and subretry in
+ * the dump as after restoring the dump this value may no longer be
+ * relevant.
*/
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index b0f2a17..8edbbca 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -88,6 +88,11 @@ CATALOG(pg_subscription,6100,SubscriptionRelationId) BKI_SHARED_RELATION BKI_ROW
bool subdisableonerr; /* True if a worker error should cause the
* subscription to be disabled */
+ bool subretry BKI_DEFAULT(f); /* True if previous change failed
+ * to be applied while there were
+ * any active parallel apply
+ * workers */
+
#ifdef CATALOG_VARLEN /* variable-length fields start here */
/* Connection string to the publisher */
text subconninfo BKI_FORCE_NOT_NULL;
@@ -131,6 +136,8 @@ typedef struct Subscription
bool disableonerr; /* Indicates if the subscription should be
* automatically disabled if a worker error
* occurs */
+ bool retry; /* Indicates if previous change failed to be
+ * applied using a parallel apply worker */
char *conninfo; /* Connection string to the publisher */
char *slotname; /* Name of the replication slot */
char *synccommit; /* Synchronous commit setting for worker */
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index f3b2f2d..42c33a4 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -308,6 +308,8 @@ extern void pa_decr_and_wait_stream_block(void);
extern void pa_xact_finish(ParallelApplyWorkerInfo *winfo,
XLogRecPtr remote_lsn);
+extern bool pa_have_active_worker(void);
+
#define isParallelApplyWorker(worker) ((worker)->apply_leader_pid != InvalidPid)
static inline bool
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 83d6956..4054a5f 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -74,8 +74,16 @@ sub test_streaming
'check extra columns contain local defaults');
# Test the streaming in binary mode
+ my $oldpid = $node_publisher->safe_psql('postgres',
+ "SELECT pid FROM pg_stat_replication WHERE application_name = '$appname' AND state = 'streaming';"
+ );
$node_subscriber->safe_psql('postgres',
"ALTER SUBSCRIPTION tap_sub SET (binary = on)");
+ $node_publisher->poll_query_until('postgres',
+ "SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = '$appname' AND state = 'streaming';"
+ )
+ or die
+ "Timed out while waiting for apply to restart after changing SUBSCRIPTION";
# Check the subscriber log from now on.
$offset = -s $node_subscriber->logfile;
@@ -450,6 +458,61 @@ $result =
is($result, qq(5000),
'data replicated to subscriber by serializing messages to disk');
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# ============================================================================
+# Test re-apply a failed streaming transaction using the leader apply
+# worker and apply subsequent streaming transaction using the parallel apply
+# worker after this retry succeeds.
+# ============================================================================
+
+$node_subscriber->safe_psql('postgres',
+ "CREATE UNIQUE INDEX idx_tab on test_tab_2(a)");
+
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', qq{
+BEGIN;
+INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+INSERT INTO test_tab_2 values(1);
+COMMIT;});
+
+# Check if the parallel apply worker is not started because the above
+# transaction failed to be applied.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? parallel apply workers are not used for retries/,
+ $offset);
+
+# Drop the unique index on the subscriber, now it works.
+$node_subscriber->safe_psql('postgres', "DROP INDEX idx_tab");
+
+# Wait for this streaming transaction to be applied in the apply worker.
+$node_publisher->wait_for_catchup($appname);
+
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5001), 'data replicated to subscriber after dropping index');
+
+# After successfully retrying to apply a failed streaming transaction, apply
+# the following streaming transaction using the parallel apply worker.
+
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(5001, 10000) s(i)");
+
+check_parallel_log($node_subscriber, $offset, 1, 'COMMIT');
+
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(10001),
+ 'data replicated to subscriber using the parallel apply worker');
+
$node_subscriber->stop;
$node_publisher->stop;
--
2.7.2.windows.1
[application/octet-stream] v78-0001-Add-a-main_worker_pid-to-pg_stat_subscription.patch (9.4K, ../../OS0PR01MB5716863B23DBAD186F64ADF194FF9@OS0PR01MB5716.jpnprd01.prod.outlook.com/3-v78-0001-Add-a-main_worker_pid-to-pg_stat_subscription.patch)
download | inline diff:
From c2feee2f08c68608674da45c894f3a110dbad3bd Mon Sep 17 00:00:00 2001
From: "houzj.fnst" <[email protected]>
Date: Thu, 6 Oct 2022 14:42:24 +0800
Subject: [PATCH v78 1/4] Add a main_worker_pid to pg_stat_subscription
main_worker_pid is Process ID of the leader apply worker, if this process is a
apply parallel worker. NULL if this process is a leader apply worker or a
synchronization worker.
The new column can make it easier to distinguish leader apply worker and apply
parallel worker which is also similar to the 'leader_pid' column in
pg_stat_activity.
---
doc/src/sgml/logical-replication.sgml | 3 ++-
doc/src/sgml/monitoring.sgml | 26 ++++++++++++++++++------
src/backend/catalog/system_views.sql | 1 +
src/backend/replication/logical/launcher.c | 32 ++++++++++++++++--------------
src/include/catalog/pg_proc.dat | 6 +++---
src/test/regress/expected/rules.out | 3 ++-
6 files changed, 45 insertions(+), 26 deletions(-)
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 54f48be..8029fab 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1692,7 +1692,8 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
subscription. A disabled subscription or a crashed subscription will have
zero rows in this view. If the initial data synchronization of any
table is in progress, there will be additional workers for the tables
- being synchronized.
+ being synchronized. Moreover, if the streaming transaction is applied in
+ parallel, there will be additional workers.
</para>
</sect1>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index cf220c3..c2e7bdb 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -3198,11 +3198,22 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<row>
<entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>apply_leader_pid</structfield> <type>integer</type>
+ </para>
+ <para>
+ Process ID of the leader apply worker, if this process is a apply
+ parallel worker. NULL if this process is a leader apply worker or a
+ synchronization worker.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
<structfield>relid</structfield> <type>oid</type>
</para>
<para>
OID of the relation that the worker is synchronizing; null for the
- main apply worker
+ main apply worker and the parallel apply worker
</para></entry>
</row>
@@ -3212,7 +3223,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Last write-ahead log location received, the initial value of
- this field being 0
+ this field being 0; null for the parallel apply worker
</para></entry>
</row>
@@ -3221,7 +3232,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_send_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Send time of last message received from origin WAL sender
+ Send time of last message received from origin WAL sender; null for the
+ parallel apply worker
</para></entry>
</row>
@@ -3230,7 +3242,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_receipt_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Receipt time of last message received from origin WAL sender
+ Receipt time of last message received from origin WAL sender; null for
+ the parallel apply worker
</para></entry>
</row>
@@ -3239,7 +3252,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>latest_end_lsn</structfield> <type>pg_lsn</type>
</para>
<para>
- Last write-ahead log location reported to origin WAL sender
+ Last write-ahead log location reported to origin WAL sender; null for
+ the parallel apply worker
</para></entry>
</row>
@@ -3249,7 +3263,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Time of last write-ahead log location reported to origin WAL
- sender
+ sender; null for the parallel apply worker
</para></entry>
</row>
</tbody>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 447c9b9..72e46e5 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -949,6 +949,7 @@ CREATE VIEW pg_stat_subscription AS
su.oid AS subid,
su.subname,
st.pid,
+ st.apply_leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index afb7acd..b39e0f1 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -1072,7 +1072,7 @@ IsLogicalLauncher(void)
Datum
pg_stat_get_subscription(PG_FUNCTION_ARGS)
{
-#define PG_STAT_GET_SUBSCRIPTION_COLS 8
+#define PG_STAT_GET_SUBSCRIPTION_COLS 9
Oid subid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
int i;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
@@ -1098,10 +1098,6 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
if (OidIsValid(subid) && worker.subid != subid)
continue;
- /* Skip if this is a parallel apply worker */
- if (isParallelApplyWorker(&worker))
- continue;
-
worker_pid = worker.proc->pid;
values[0] = ObjectIdGetDatum(worker.subid);
@@ -1110,26 +1106,32 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
else
nulls[1] = true;
values[2] = Int32GetDatum(worker_pid);
- if (XLogRecPtrIsInvalid(worker.last_lsn))
+
+ if (worker.apply_leader_pid == InvalidPid)
nulls[3] = true;
else
- values[3] = LSNGetDatum(worker.last_lsn);
- if (worker.last_send_time == 0)
+ values[3] = Int32GetDatum(worker.apply_leader_pid);
+
+ if (XLogRecPtrIsInvalid(worker.last_lsn))
nulls[4] = true;
else
- values[4] = TimestampTzGetDatum(worker.last_send_time);
- if (worker.last_recv_time == 0)
+ values[4] = LSNGetDatum(worker.last_lsn);
+ if (worker.last_send_time == 0)
nulls[5] = true;
else
- values[5] = TimestampTzGetDatum(worker.last_recv_time);
- if (XLogRecPtrIsInvalid(worker.reply_lsn))
+ values[5] = TimestampTzGetDatum(worker.last_send_time);
+ if (worker.last_recv_time == 0)
nulls[6] = true;
else
- values[6] = LSNGetDatum(worker.reply_lsn);
- if (worker.reply_time == 0)
+ values[6] = TimestampTzGetDatum(worker.last_recv_time);
+ if (XLogRecPtrIsInvalid(worker.reply_lsn))
nulls[7] = true;
else
- values[7] = TimestampTzGetDatum(worker.reply_time);
+ values[7] = LSNGetDatum(worker.reply_lsn);
+ if (worker.reply_time == 0)
+ nulls[8] = true;
+ else
+ values[8] = TimestampTzGetDatum(worker.reply_time);
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
values, nulls);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3810de7..dbca793 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5430,9 +5430,9 @@
proname => 'pg_stat_get_subscription', prorows => '10', proisstrict => 'f',
proretset => 't', provolatile => 's', proparallel => 'r',
prorettype => 'record', proargtypes => 'oid',
- proallargtypes => '{oid,oid,oid,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
- proargmodes => '{i,o,o,o,o,o,o,o,o}',
- proargnames => '{subid,subid,relid,pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
+ proallargtypes => '{oid,oid,oid,int4,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{subid,subid,relid,pid,apply_leader_pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
prosrc => 'pg_stat_get_subscription' },
{ oid => '2026', descr => 'statistics: current backend PID',
proname => 'pg_backend_pid', provolatile => 's', proparallel => 'r',
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index fb9f936..7e6ea60 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2094,6 +2094,7 @@ pg_stat_ssl| SELECT s.pid,
pg_stat_subscription| SELECT su.oid AS subid,
su.subname,
st.pid,
+ st.apply_leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
@@ -2101,7 +2102,7 @@ pg_stat_subscription| SELECT su.oid AS subid,
st.latest_end_lsn,
st.latest_end_time
FROM (pg_subscription su
- LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
+ LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, apply_leader_pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
pg_stat_subscription_stats| SELECT ss.subid,
s.subname,
ss.apply_error_count,
--
2.7.2.windows.1
[application/octet-stream] v78-0002-Stop-extra-worker-if-GUC-was-changed.patch (4.2K, ../../OS0PR01MB5716863B23DBAD186F64ADF194FF9@OS0PR01MB5716.jpnprd01.prod.outlook.com/4-v78-0002-Stop-extra-worker-if-GUC-was-changed.patch)
download | inline diff:
From c9431440f992f76883c14f7519c187365f27a09d Mon Sep 17 00:00:00 2001
From: sherlockcpp <[email protected]>
Date: Sat, 17 Dec 2022 20:43:21 +0800
Subject: [PATCH v78 2/4] Stop extra worker if GUC was changed
If the max_parallel_apply_workers_per_subscription is changed to a
lower value, try to stop free workers in the pool to keep the number of
workers lower than half of the max_parallel_apply_workers_per_subscription
---
.../replication/logical/applyparallelworker.c | 60 ++++++++++++++++++----
src/backend/replication/logical/worker.c | 7 +++
src/include/replication/worker_internal.h | 1 +
3 files changed, 57 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 2e5914d..ab758fe 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -543,6 +543,25 @@ pa_find_worker(TransactionId xid)
}
/*
+ * Stop the given parallel apply worker and free the corresponding info.
+ */
+static void
+pa_stop_worker(ParallelApplyWorkerInfo *winfo)
+{
+ int slot_no;
+ uint16 generation;
+
+ SpinLockAcquire(&winfo->shared->mutex);
+ generation = winfo->shared->logicalrep_worker_generation;
+ slot_no = winfo->shared->logicalrep_worker_slot_no;
+ SpinLockRelease(&winfo->shared->mutex);
+
+ logicalrep_pa_worker_stop(slot_no, generation);
+
+ pa_free_worker_info(winfo);
+}
+
+/*
* Makes the worker available for reuse.
*
* This removes the parallel apply worker entry from the hash table so that it
@@ -577,23 +596,42 @@ pa_free_worker(ParallelApplyWorkerInfo *winfo)
list_length(ParallelApplyWorkerPool) >
(max_parallel_apply_workers_per_subscription / 2))
{
- int slot_no;
- uint16 generation;
-
- SpinLockAcquire(&winfo->shared->mutex);
- generation = winfo->shared->logicalrep_worker_generation;
- slot_no = winfo->shared->logicalrep_worker_slot_no;
- SpinLockRelease(&winfo->shared->mutex);
+ pa_stop_worker(winfo);
+ return;
+ }
- logicalrep_pa_worker_stop(slot_no, generation);
+ winfo->in_use = false;
+ winfo->serialize_changes = false;
+}
- pa_free_worker_info(winfo);
+/*
+ * Try to stop parallel apply workers that are not in use to keep the number of
+ * workers lower than half of the max_parallel_apply_workers_per_subscription.
+ */
+void
+pa_stop_idle_workers(void)
+{
+ List *active_workers;
+ ListCell *lc;
+ int max_applyworkers = max_parallel_apply_workers_per_subscription / 2;
+ if (list_length(ParallelApplyWorkerPool) <= max_applyworkers)
return;
+
+ active_workers = list_copy(ParallelApplyWorkerPool);
+
+ foreach(lc, active_workers)
+ {
+ ParallelApplyWorkerInfo *winfo = (ParallelApplyWorkerInfo *) lfirst(lc);
+
+ pa_stop_worker(winfo);
+
+ /* Recheck the number of workers. */
+ if (list_length(ParallelApplyWorkerPool) <= max_applyworkers)
+ break;
}
- winfo->in_use = false;
- winfo->serialize_changes = false;
+ list_free(active_workers);
}
/*
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 79cda39..c7be76d 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -3630,6 +3630,13 @@ LogicalRepApplyLoop(XLogRecPtr last_received)
{
ConfigReloadPending = false;
ProcessConfigFile(PGC_SIGHUP);
+
+ /*
+ * Try to stop free workers in the pool in case the
+ * max_parallel_apply_workers_per_subscription is changed to a
+ * lower value.
+ */
+ pa_stop_idle_workers();
}
if (rc & WL_TIMEOUT)
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index db891ee..1d9d7d6 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -274,6 +274,7 @@ extern void set_apply_error_context_origin(char *originname);
/* Parallel apply worker setup and interactions */
extern void pa_allocate_worker(TransactionId xid);
extern ParallelApplyWorkerInfo *pa_find_worker(TransactionId xid);
+extern void pa_stop_idle_workers(void);
extern void pa_detach_all_error_mq(void);
extern bool pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes,
--
2.7.2.windows.1
[application/octet-stream] v78-0003-Add-GUC-stream_serialize_threshold-and-test-seri.patch (12.5K, ../../OS0PR01MB5716863B23DBAD186F64ADF194FF9@OS0PR01MB5716.jpnprd01.prod.outlook.com/5-v78-0003-Add-GUC-stream_serialize_threshold-and-test-seri.patch)
download | inline diff:
From 02992050a5425cc055e3a1ec3c99f8fea847bea1 Mon Sep 17 00:00:00 2001
From: Amit Kapila <[email protected]>
Date: Mon, 2 Jan 2023 15:37:25 +0530
Subject: [PATCH v78 3/4] Add GUC stream_serialize_threshold and test
serializing messages to disk.
---
doc/src/sgml/config.sgml | 32 +++++
.../replication/logical/applyparallelworker.c | 12 ++
src/backend/replication/logical/worker.c | 9 ++
src/backend/utils/misc/guc_tables.c | 14 ++
src/include/replication/worker_internal.h | 4 +
src/test/subscription/t/015_stream.pl | 144 ++++++++++++++++++++-
6 files changed, 212 insertions(+), 3 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 2fec613..74bb623 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11650,6 +11650,38 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
+ <varlistentry id="guc-stream-serialize-threshold" xreflabel="stream_serialize_threshold">
+ <term><varname>stream_serialize_threshold</varname> (<type>integer</type>)
+ <indexterm>
+ <primary><varname>stream_serialize_threshold</varname> configuration parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Forces the leader apply worker to serialize messages to files after
+ sending specified amount of streaming chunks to the parallel apply
+ worker. Setting this to zero serialize all messages. A value of
+ <literal>-1</literal> (the default) disables this feature. This is
+ intended to test serialization to files with
+ <literal>streaming = parallel</literal>.
+ </para>
+
+ <para>
+ When logical replication subscription <literal>streaming</literal>
+ parameter is set to <literal>parallel</literal>, the leader apply worker
+ sends messages to parallel workers with a timeout. By default, the
+ leader apply worker will serialize the remaining messages to files if
+ the timeout is exceeded. If this option is set to any value other than
+ <literal>-1</literal>, serialize to files even without timeout.
+ </para>
+
+ <para>
+ This parameter can only be set in the <filename>postgresql.conf</filename>
+ file or on the server command line.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</sect1>
<sect1 id="runtime-config-short">
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index ab758fe..a7ce57b 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -254,6 +254,9 @@ static ParallelApplyWorkerInfo *stream_apply_worker = NULL;
/* A list to maintain subtransactions, if any. */
static List *subxactlist = NIL;
+/* GUC variable */
+int stream_serialize_threshold = -1;
+
static void pa_free_worker_info(ParallelApplyWorkerInfo *winfo);
static ParallelTransState pa_get_xact_state(ParallelApplyWorkerShared *wshared);
static PartialFileSetState pa_get_fileset_state(void);
@@ -1187,6 +1190,15 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ /* Force to serialize messages if stream_serialize_threshold is reached. */
+ if (stream_serialize_threshold != -1 &&
+ (stream_serialize_threshold == 0 ||
+ stream_serialize_threshold < parallel_stream_nchunks))
+ {
+ parallel_stream_nchunks = 0;
+ return false;
+ }
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index c7be76d..5c8ce97 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -328,6 +328,12 @@ static TransactionId stream_xid = InvalidTransactionId;
static uint32 parallel_stream_nchanges = 0;
/*
+ * The number of streaming chunks sent by leader apply worker during one
+ * streamed transaction. This is only used when stream_serialize_threshold > 0.
+ */
+uint32 parallel_stream_nchunks = 0;
+
+/*
* We enable skipping all data modification changes (INSERT, UPDATE, etc.) for
* the subscription if the remote transaction's finish LSN matches the subskiplsn.
* Once we start skipping changes, we don't stop it until we skip all changes of
@@ -1521,6 +1527,9 @@ apply_handle_stream_start(StringInfo s)
case TRANS_LEADER_SEND_TO_PARALLEL:
Assert(winfo);
+ if (stream_serialize_threshold > 0)
+ parallel_stream_nchunks++;
+
/*
* Once we start serializing the changes, the parallel apply
* worker will wait for the leader to release the stream lock
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 92545b4..302ceb7 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -61,6 +61,7 @@
#include "replication/logicallauncher.h"
#include "replication/slot.h"
#include "replication/syncrep.h"
+#include "replication/worker_internal.h"
#include "storage/bufmgr.h"
#include "storage/large_object.h"
#include "storage/pg_shmem.h"
@@ -3015,6 +3016,19 @@ struct config_int ConfigureNamesInt[] =
},
{
+ {"stream_serialize_threshold", PGC_SIGHUP, DEVELOPER_OPTIONS,
+ gettext_noop("Forces the leader apply worker to serialize messages "
+ "to files after sending specified amount of streaming "
+ "chunks in streaming parallel mode."),
+ gettext_noop("A value of -1 disables this feature."),
+ GUC_NOT_IN_SAMPLE
+ },
+ &stream_serialize_threshold,
+ -1, -1, INT_MAX,
+ NULL, NULL, NULL
+ },
+
+ {
{"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
gettext_noop("Sets the amount of time to wait before forcing "
"log file rotation."),
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index 1d9d7d6..f3b2f2d 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -225,6 +225,10 @@ extern PGDLLIMPORT LogicalRepWorker *MyLogicalRepWorker;
extern PGDLLIMPORT bool in_remote_transaction;
+extern PGDLLIMPORT int stream_serialize_threshold;
+
+extern PGDLLIMPORT uint32 parallel_stream_nchunks;
+
extern void logicalrep_worker_attach(int slot);
extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
bool only_running);
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8..83d6956 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -133,13 +133,20 @@ sub test_streaming
# Create publisher node
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
-$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_work_mem = 64kB');
+$node_publisher->append_conf(
+ 'postgresql.conf', qq(
+max_prepared_transactions = 10
+logical_decoding_work_mem = 64kB
+));
$node_publisher->start;
# Create subscriber node
my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->append_conf(
+ 'postgresql.conf', qq(
+max_prepared_transactions = 10
+));
$node_subscriber->start;
# Create some preexisting content on publisher
@@ -170,7 +177,7 @@ my $appname = 'tap_sub';
# Test using streaming mode 'on'
################################
$node_subscriber->safe_psql('postgres',
- "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (streaming = on)"
+ "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (streaming = on, two_phase = on)"
);
# Wait for initial table sync to finish
@@ -312,6 +319,137 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Test serializing messages to disk
+
+# Set stream_serialize_threshold to zero, so the messages will be serialized to disk.
+$node_subscriber->safe_psql('postgres',
+ 'ALTER SYSTEM SET stream_serialize_threshold = 0;');
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+# Serialize the COMMIT transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? opening file ".*\.changes" for streamed changes/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the PREPARE transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? opening file ".*\.changes" for streamed changes/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the ABORT top-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ ROLLBACK;
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? opening file ".*\.changes" for streamed changes/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(5001, 10000) s(i);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? opening file ".*\.changes" for streamed changes/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
$node_subscriber->stop;
$node_publisher->stop;
--
2.7.2.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-10 11:47 ` Dilip Kumar <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: Dilip Kumar @ 2023-01-10 11:47 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>
On Tue, Jan 10, 2023 at 10:26 AM [email protected]
<[email protected]> wrote:
>
> On Monday, January 9, 2023 4:51 PM Amit Kapila <[email protected]> wrote:
> >
> > On Sun, Jan 8, 2023 at 11:32 AM [email protected]
> > <[email protected]> wrote:
> > >
> > > On Sunday, January 8, 2023 11:59 AM [email protected]
> > <[email protected]> wrote:
> > > > Attach the updated patch set.
> > >
> > > Sorry, the commit message of 0001 was accidentally deleted, just
> > > attach the same patch set again with commit message.
> > >
> >
> > Pushed the first (0001) patch.
>
> Thanks for pushing, here are the remaining patches.
> I reordered the patch number to put patches that are easier to
> commit in the front of others.
I was looking into 0001, IMHO the pid should continue to represent the
main apply worker. So the pid will always show the main apply worker
which is actually receiving all the changes for the subscription (in
short working as logical receiver) and if it is applying changes
through a parallel worker then it should put the parallel worker pid
in a new column called 'parallel_worker_pid' or
'parallel_apply_worker_pid' otherwise NULL. Thoughts?
--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-12 04:23 ` Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
1 sibling, 2 replies; 105+ messages in thread
From: Peter Smith @ 2023-01-12 04:23 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
Hi, here are some review comments for patch v78-0001.
======
General
1. (terminology)
AFAIK everywhere until now we’ve been referring everywhere
(docs/comments/code) to the parent apply worker as the "leader apply
worker". Not the "main apply worker". Not the "apply leader worker".
Not any other variations...
From this POV I think the worker member "apply_leader_pid" would be
better named "leader_apply_pid", but I see that this was already
committed to HEAD differently.
Maybe it is not possible (or you don't want) to change that internal
member name but IMO at least all the new code and docs should try to
be using consistent terminology (e.g. leader_apply_XXX) where
possible.
======
Commit message
2.
main_worker_pid is Process ID of the leader apply worker, if this process is a
apply parallel worker. NULL if this process is a leader apply worker or a
synchronization worker.
IIUC, this text is just cut/paste from the monitoring.sgml. In a
review comment below I suggest some changes to that text, so then this
commit message should also change to be the same.
~~
3.
The new column can make it easier to distinguish leader apply worker and apply
parallel worker which is also similar to the 'leader_pid' column in
pg_stat_activity.
SUGGESTION
The new column makes it easier to distinguish parallel apply workers
from other kinds of workers. It is implemented this way to be similar
to the 'leader_pid' column in pg_stat_activity.
======
doc/src/sgml/logical-replication.sgml
4.
+ being synchronized. Moreover, if the streaming transaction is applied in
+ parallel, there will be additional workers.
SUGGESTION
there will be additional workers -> there may be additional parallel
apply workers
======
doc/src/sgml/monitoring.sgml
5. pg_stat_subscription
@@ -3198,11 +3198,22 @@ SELECT pid, wait_event_type, wait_event FROM
pg_stat_activity WHERE wait_event i
<row>
<entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>apply_leader_pid</structfield> <type>integer</type>
+ </para>
+ <para>
+ Process ID of the leader apply worker, if this process is a apply
+ parallel worker. NULL if this process is a leader apply worker or a
+ synchronization worker.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
<structfield>relid</structfield> <type>oid</type>
</para>
<para>
OID of the relation that the worker is synchronizing; null for the
- main apply worker
+ main apply worker and the parallel apply worker
</para></entry>
</row>
5a.
(Same as general comment #1 about terminology)
"apply_leader_pid" --> "leader_apply_pid"
~~
5b.
The current text feels awkward. I see it was copied from the similar
text of 'pg_stat_activity' but perhaps it can be simplified a bit.
SUGGESTION
Process ID of the leader apply worker if this process is a parallel
apply worker; otherwise NULL.
~~
5c.
BEFORE
null for the main apply worker and the parallel apply worker
AFTER
null for the leader apply worker and parallel apply workers
~~
5c.
<structfield>relid</structfield> <type>oid</type>
</para>
<para>
OID of the relation that the worker is synchronizing; null for the
- main apply worker
+ main apply worker and the parallel apply worker
</para></entry>
main apply worker -> leader apply worker
~~~
6.
@@ -3212,7 +3223,7 @@ SELECT pid, wait_event_type, wait_event FROM
pg_stat_activity WHERE wait_event i
</para>
<para>
Last write-ahead log location received, the initial value of
- this field being 0
+ this field being 0; null for the parallel apply worker
</para></entry>
</row>
BEFORE
null for the parallel apply worker
AFTER
null for parallel apply workers
~~~
7.
@@ -3221,7 +3232,8 @@ SELECT pid, wait_event_type, wait_event FROM
pg_stat_activity WHERE wait_event i
<structfield>last_msg_send_time</structfield> <type>timestamp
with time zone</type>
</para>
<para>
- Send time of last message received from origin WAL sender
+ Send time of last message received from origin WAL sender; null for the
+ parallel apply worker
</para></entry>
</row>
(same as #6)
BEFORE
null for the parallel apply worker
AFTER
null for parallel apply workers
~~~
8.
@@ -3230,7 +3242,8 @@ SELECT pid, wait_event_type, wait_event FROM
pg_stat_activity WHERE wait_event i
<structfield>last_msg_receipt_time</structfield>
<type>timestamp with time zone</type>
</para>
<para>
- Receipt time of last message received from origin WAL sender
+ Receipt time of last message received from origin WAL sender; null for
+ the parallel apply worker
</para></entry>
</row>
(same as #6)
BEFORE
null for the parallel apply worker
AFTER
null for parallel apply workers
~~~
9.
@@ -3239,7 +3252,8 @@ SELECT pid, wait_event_type, wait_event FROM
pg_stat_activity WHERE wait_event i
<structfield>latest_end_lsn</structfield> <type>pg_lsn</type>
</para>
<para>
- Last write-ahead log location reported to origin WAL sender
+ Last write-ahead log location reported to origin WAL sender; null for
+ the parallel apply worker
</para></entry>
</row>
(same as #6)
BEFORE
null for the parallel apply worker
AFTER
null for parallel apply workers
~~~
10.
@@ -3249,7 +3263,7 @@ SELECT pid, wait_event_type, wait_event FROM
pg_stat_activity WHERE wait_event i
</para>
<para>
Time of last write-ahead log location reported to origin WAL
- sender
+ sender; null for the parallel apply worker
</para></entry>
</row>
</tbody>
(same as #6)
BEFORE
null for the parallel apply worker
AFTER
null for parallel apply workers
======
src/backend/catalog/system_views.sql
11.
@@ -949,6 +949,7 @@ CREATE VIEW pg_stat_subscription AS
su.oid AS subid,
su.subname,
st.pid,
+ st.apply_leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
(Same as general comment #1 about terminology)
"apply_leader_pid" --> "leader_apply_pid"
======
src/backend/replication/logical/launcher.c
12.
+ if (worker.apply_leader_pid == InvalidPid)
nulls[3] = true;
else
- values[3] = LSNGetDatum(worker.last_lsn);
- if (worker.last_send_time == 0)
+ values[3] = Int32GetDatum(worker.apply_leader_pid);
+
12a.
(Same as general comment #1 about terminology)
"apply_leader_pid" --> "leader_apply_pid"
~~
12b.
I wondered if here the code should be using the
isParallelApplyWorker(worker) macro here for readability.
e.g.
if (isParallelApplyWorker(worker))
values[3] = Int32GetDatum(worker.apply_leader_pid);
else
nulls[3] = true;
======
src/include/catalog/pg_proc.dat
13.
+ proallargtypes =>
'{oid,oid,oid,int4,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o}',
+ proargnames =>
'{subid,subid,relid,pid,apply_leader_pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
(Same as general comment #1 about terminology)
"apply_leader_pid" --> "leader_apply_pid"
======
src/test/regress/expected/rules.out
14.
@@ -2094,6 +2094,7 @@ pg_stat_ssl| SELECT s.pid,
pg_stat_subscription| SELECT su.oid AS subid,
su.subname,
st.pid,
+ st.apply_leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
@@ -2101,7 +2102,7 @@ pg_stat_subscription| SELECT su.oid AS subid,
st.latest_end_lsn,
st.latest_end_time
FROM (pg_subscription su
- LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid,
pid, received_lsn, last_msg_send_time, last_msg_receipt_time,
latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
+ LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid,
pid, apply_leader_pid, received_lsn, last_msg_send_time,
last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid
= su.oid)));
pg_stat_subscription_stats| SELECT ss.subid,
s.subname,
ss.apply_error_count,
(Same comment as elsewhere)
"apply_leader_pid" --> "leader_apply_pid"
------
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-12 05:04 ` Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
1 sibling, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-01-12 05:04 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Thu, Jan 12, 2023 at 9:54 AM Peter Smith <[email protected]> wrote:
>
>
> doc/src/sgml/monitoring.sgml
>
> 5. pg_stat_subscription
>
> @@ -3198,11 +3198,22 @@ SELECT pid, wait_event_type, wait_event FROM
> pg_stat_activity WHERE wait_event i
>
> <row>
> <entry role="catalog_table_entry"><para role="column_definition">
> + <structfield>apply_leader_pid</structfield> <type>integer</type>
> + </para>
> + <para>
> + Process ID of the leader apply worker, if this process is a apply
> + parallel worker. NULL if this process is a leader apply worker or a
> + synchronization worker.
> + </para></entry>
> + </row>
> +
> + <row>
> + <entry role="catalog_table_entry"><para role="column_definition">
> <structfield>relid</structfield> <type>oid</type>
> </para>
> <para>
> OID of the relation that the worker is synchronizing; null for the
> - main apply worker
> + main apply worker and the parallel apply worker
> </para></entry>
> </row>
>
> 5a.
>
> (Same as general comment #1 about terminology)
>
> "apply_leader_pid" --> "leader_apply_pid"
>
How about naming this as just leader_pid? I think it could be helpful
in the future if we decide to parallelize initial sync (aka parallel
copy) because then we could use this for the leader PID of parallel
sync workers as well.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-12 10:51 ` shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: shveta malik @ 2023-01-12 10:51 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Peter Smith <[email protected]>; [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; shveta malik <[email protected]>
On Thu, Jan 12, 2023 at 10:34 AM Amit Kapila <[email protected]> wrote:
>
> On Thu, Jan 12, 2023 at 9:54 AM Peter Smith <[email protected]> wrote:
> >
> >
> > doc/src/sgml/monitoring.sgml
> >
> > 5. pg_stat_subscription
> >
> > @@ -3198,11 +3198,22 @@ SELECT pid, wait_event_type, wait_event FROM
> > pg_stat_activity WHERE wait_event i
> >
> > <row>
> > <entry role="catalog_table_entry"><para role="column_definition">
> > + <structfield>apply_leader_pid</structfield> <type>integer</type>
> > + </para>
> > + <para>
> > + Process ID of the leader apply worker, if this process is a apply
> > + parallel worker. NULL if this process is a leader apply worker or a
> > + synchronization worker.
> > + </para></entry>
> > + </row>
> > +
> > + <row>
> > + <entry role="catalog_table_entry"><para role="column_definition">
> > <structfield>relid</structfield> <type>oid</type>
> > </para>
> > <para>
> > OID of the relation that the worker is synchronizing; null for the
> > - main apply worker
> > + main apply worker and the parallel apply worker
> > </para></entry>
> > </row>
> >
> > 5a.
> >
> > (Same as general comment #1 about terminology)
> >
> > "apply_leader_pid" --> "leader_apply_pid"
> >
>
> How about naming this as just leader_pid? I think it could be helpful
> in the future if we decide to parallelize initial sync (aka parallel
> copy) because then we could use this for the leader PID of parallel
> sync workers as well.
>
> --
I still prefer leader_apply_pid.
leader_pid does not tell which 'operation' it belongs to. 'apply'
gives the clarity that it is apply related process.
The terms used in patch look very confusing. I had to read a few lines
multiple times to understand it.
1.
Summary says 'main_worker_pid' to be added but I do not see
'main_worker_pid' added in pg_stat_subscription, instead I see
'apply_leader_pid'. Am I missing something? Also, as stated above
'leader_apply_pid' makes more sense.
it is better to correct it everywhere (apply leader-->leader apply).
Once that is done, it can be reviewed again.
thanks
Shveta
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
@ 2023-01-12 11:07 ` Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 02:52 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
0 siblings, 2 replies; 105+ messages in thread
From: Amit Kapila @ 2023-01-12 11:07 UTC (permalink / raw)
To: shveta malik <[email protected]>; +Cc: Peter Smith <[email protected]>; [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Thu, Jan 12, 2023 at 4:21 PM shveta malik <[email protected]> wrote:
>
> On Thu, Jan 12, 2023 at 10:34 AM Amit Kapila <[email protected]> wrote:
> >
> > On Thu, Jan 12, 2023 at 9:54 AM Peter Smith <[email protected]> wrote:
> > >
> > >
> > > doc/src/sgml/monitoring.sgml
> > >
> > > 5. pg_stat_subscription
> > >
> > > @@ -3198,11 +3198,22 @@ SELECT pid, wait_event_type, wait_event FROM
> > > pg_stat_activity WHERE wait_event i
> > >
> > > <row>
> > > <entry role="catalog_table_entry"><para role="column_definition">
> > > + <structfield>apply_leader_pid</structfield> <type>integer</type>
> > > + </para>
> > > + <para>
> > > + Process ID of the leader apply worker, if this process is a apply
> > > + parallel worker. NULL if this process is a leader apply worker or a
> > > + synchronization worker.
> > > + </para></entry>
> > > + </row>
> > > +
> > > + <row>
> > > + <entry role="catalog_table_entry"><para role="column_definition">
> > > <structfield>relid</structfield> <type>oid</type>
> > > </para>
> > > <para>
> > > OID of the relation that the worker is synchronizing; null for the
> > > - main apply worker
> > > + main apply worker and the parallel apply worker
> > > </para></entry>
> > > </row>
> > >
> > > 5a.
> > >
> > > (Same as general comment #1 about terminology)
> > >
> > > "apply_leader_pid" --> "leader_apply_pid"
> > >
> >
> > How about naming this as just leader_pid? I think it could be helpful
> > in the future if we decide to parallelize initial sync (aka parallel
> > copy) because then we could use this for the leader PID of parallel
> > sync workers as well.
> >
> > --
>
> I still prefer leader_apply_pid.
> leader_pid does not tell which 'operation' it belongs to. 'apply'
> gives the clarity that it is apply related process.
>
But then do you suggest that tomorrow if we allow parallel sync
workers then we have a separate column leader_sync_pid? I think that
doesn't sound like a good idea and moreover one can refer to docs for
clarification.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-12 12:34 ` [email protected] <[email protected]>
2023-01-13 02:25 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
1 sibling, 3 replies; 105+ messages in thread
From: [email protected] @ 2023-01-12 12:34 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; shveta malik <[email protected]>; +Cc: Peter Smith <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Thursday, January 12, 2023 7:08 PM Amit Kapila <[email protected]> wrote:
>
> On Thu, Jan 12, 2023 at 4:21 PM shveta malik <[email protected]> wrote:
> >
> > On Thu, Jan 12, 2023 at 10:34 AM Amit Kapila <[email protected]>
> wrote:
> > >
> > > On Thu, Jan 12, 2023 at 9:54 AM Peter Smith <[email protected]>
> wrote:
> > > >
> > > >
> > > > doc/src/sgml/monitoring.sgml
> > > >
> > > > 5. pg_stat_subscription
> > > >
> > > > @@ -3198,11 +3198,22 @@ SELECT pid, wait_event_type, wait_event
> > > > FROM pg_stat_activity WHERE wait_event i
> > > >
> > > > <row>
> > > > <entry role="catalog_table_entry"><para
> > > > role="column_definition">
> > > > + <structfield>apply_leader_pid</structfield>
> <type>integer</type>
> > > > + </para>
> > > > + <para>
> > > > + Process ID of the leader apply worker, if this process is a apply
> > > > + parallel worker. NULL if this process is a leader apply worker or a
> > > > + synchronization worker.
> > > > + </para></entry>
> > > > + </row>
> > > > +
> > > > + <row>
> > > > + <entry role="catalog_table_entry"><para
> > > > + role="column_definition">
> > > > <structfield>relid</structfield> <type>oid</type>
> > > > </para>
> > > > <para>
> > > > OID of the relation that the worker is synchronizing; null for the
> > > > - main apply worker
> > > > + main apply worker and the parallel apply worker
> > > > </para></entry>
> > > > </row>
> > > >
> > > > 5a.
> > > >
> > > > (Same as general comment #1 about terminology)
> > > >
> > > > "apply_leader_pid" --> "leader_apply_pid"
> > > >
> > >
> > > How about naming this as just leader_pid? I think it could be
> > > helpful in the future if we decide to parallelize initial sync (aka
> > > parallel
> > > copy) because then we could use this for the leader PID of parallel
> > > sync workers as well.
> > >
> > > --
> >
> > I still prefer leader_apply_pid.
> > leader_pid does not tell which 'operation' it belongs to. 'apply'
> > gives the clarity that it is apply related process.
> >
>
> But then do you suggest that tomorrow if we allow parallel sync workers then
> we have a separate column leader_sync_pid? I think that doesn't sound like a
> good idea and moreover one can refer to docs for clarification.
I agree that leader_pid would be better not only for future parallel copy sync feature,
but also it's more consistent with the leader_pid column in pg_stat_activity.
And here is the version patch which addressed Peter's comments and renamed all
the related stuff to leader_pid.
Best Regards,
Hou zj
Attachments:
[application/octet-stream] v79-0004-Retry-to-apply-streaming-xact-only-in-apply-work.patch (21.1K, ../../OS0PR01MB5716C663C85687E76672327094FD9@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v79-0004-Retry-to-apply-streaming-xact-only-in-apply-work.patch)
download | inline diff:
From 1a2ff45c9d10320f62b6fa9d3ed43fc3c6fe8b10 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Sun, 11 Dec 2022 19:16:34 +0800
Subject: [PATCH v79 4/4] Retry to apply streaming xact only in apply worker
When the subscription parameter is set streaming=parallel, the logic tries to
apply the streaming transaction using a parallel apply worker. If this
fails the parallel worker exits with an error.
In this case, retry applying the streaming transaction using the normal
streaming=on mode. This is done to avoid getting caught in a loop of the same
retry errors.
A new flag field "subretry" has been introduced to catalog "pg_subscription".
If there are any active parallel apply workers and the subscriber exits with an
error, this flag will be set true, and whenever the transaction is applied
successfully, this flag is reset false.
Now, when deciding how to apply a streaming transaction, the logic can know if
this transaction has previously failed or not (by checking the "subretry"
field).
Note: Since we add a new field 'subretry' to catalog 'pg_subscription' has been
expanded, we need bump catalog version.
---
doc/src/sgml/catalogs.sgml | 10 ++
doc/src/sgml/logical-replication.sgml | 11 +-
doc/src/sgml/ref/create_subscription.sgml | 5 +
src/backend/catalog/pg_subscription.c | 1 +
src/backend/catalog/system_views.sql | 2 +-
src/backend/commands/subscriptioncmds.c | 1 +
.../replication/logical/applyparallelworker.c | 30 ++++
src/backend/replication/logical/worker.c | 182 +++++++++++++++------
src/bin/pg_dump/pg_dump.c | 5 +-
src/include/catalog/pg_subscription.h | 7 +
src/include/replication/worker_internal.h | 2 +
src/test/subscription/t/015_stream.pl | 63 +++++++
12 files changed, 263 insertions(+), 56 deletions(-)
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index c1e4048..d918327 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -7950,6 +7950,16 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l
<row>
<entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>subretry</structfield> <type>bool</type>
+ </para>
+ <para>
+ True if previous change failed to be applied while there were any
+ active parallel apply workers, necessitating a retry.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
<structfield>subconninfo</structfield> <type>text</type>
</para>
<para>
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index f4b4e64..57e938f 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1504,12 +1504,11 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
<para>
When the streaming mode is <literal>parallel</literal>, the finish LSN of
- failed transactions may not be logged. In that case, it may be necessary to
- change the streaming mode to <literal>on</literal> or <literal>off</literal> and
- cause the same conflicts again so the finish LSN of the failed transaction will
- be written to the server log. For the usage of finish LSN, please refer to <link
- linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION ...
- SKIP</command></link>.
+ failed transactions may not be logged. In that case, the failed transaction
+ will be retried in <literal>streaming = on</literal> mode. If it fails
+ again, the finish LSN of the failed transaction will be written to the
+ server log. For the usage of finish LSN, please refer to
+ <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION ... SKIP</command></link>.
</para>
</sect1>
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
index eba72c6..decd554 100644
--- a/doc/src/sgml/ref/create_subscription.sgml
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -251,6 +251,11 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
transaction is committed. Note that if an error happens in a
parallel apply worker, the finish LSN of the remote transaction
might not be reported in the server log.
+ When applying streaming transactions, if a deadlock is detected, the
+ parallel apply worker will exit with an error. The
+ <literal>parallel</literal> mode is disregarded when retrying;
+ instead the transaction will be applied using <literal>on</literal>
+ mode.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index a56ae31..0eb5ffb 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -71,6 +71,7 @@ GetSubscription(Oid subid, bool missing_ok)
sub->stream = subform->substream;
sub->twophasestate = subform->subtwophasestate;
sub->disableonerr = subform->subdisableonerr;
+ sub->retry = subform->subretry;
/* Get conninfo */
datum = SysCacheGetAttr(SUBSCRIPTIONOID,
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index ff63405..97b145a 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1302,7 +1302,7 @@ REVOKE ALL ON pg_replication_origin_status FROM public;
REVOKE ALL ON pg_subscription FROM public;
GRANT SELECT (oid, subdbid, subskiplsn, subname, subowner, subenabled,
subbinary, substream, subtwophasestate, subdisableonerr,
- subslotname, subsynccommit, subpublications, suborigin)
+ subretry, subslotname, subsynccommit, subpublications, suborigin)
ON pg_subscription TO public;
CREATE VIEW pg_stat_subscription_stats AS
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index baff00d..b2053f7 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -636,6 +636,7 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
LOGICALREP_TWOPHASE_STATE_PENDING :
LOGICALREP_TWOPHASE_STATE_DISABLED);
values[Anum_pg_subscription_subdisableonerr - 1] = BoolGetDatum(opts.disableonerr);
+ values[Anum_pg_subscription_subretry - 1] = BoolGetDatum(false);
values[Anum_pg_subscription_subconninfo - 1] =
CStringGetTextDatum(conninfo);
if (opts.slot_name)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 777926c..fc351d7 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -315,6 +315,17 @@ pa_can_start(void)
if (!AllTablesyncsReady())
return false;
+ /*
+ * Don't use parallel apply workers for retries, because it is possible
+ * that a deadlock was detected the last time we tried to apply a
+ * transaction using a parallel apply worker.
+ */
+ if (MySubscription->retry)
+ {
+ elog(DEBUG1, "parallel apply workers are not used for retries");
+ return false;
+ }
+
return true;
}
@@ -1678,3 +1689,22 @@ pa_xact_finish(ParallelApplyWorkerInfo *winfo, XLogRecPtr remote_lsn)
pa_free_worker(winfo);
}
+
+/* Check if any active parallel apply workers. */
+bool
+pa_have_active_worker(void)
+{
+ ListCell *lc;
+
+ foreach(lc, ParallelApplyWorkerPool)
+ {
+ ParallelApplyWorkerInfo *tmp_winfo;
+
+ tmp_winfo = (ParallelApplyWorkerInfo *) lfirst(lc);
+
+ if (tmp_winfo->in_use)
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 5c8ce97..0c7bf67 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -394,7 +394,7 @@ static void stream_close_file(void);
static void send_feedback(XLogRecPtr recvpos, bool force, bool requestReply);
-static void DisableSubscriptionAndExit(void);
+static void DisableSubscriptionOnError(void);
static void apply_handle_commit_internal(LogicalRepCommitData *commit_data);
static void apply_handle_insert_internal(ApplyExecutionData *edata,
@@ -431,6 +431,8 @@ static inline void reset_apply_error_context_info(void);
static TransApplyAction get_transaction_apply_action(TransactionId xid,
ParallelApplyWorkerInfo **winfo);
+static void set_subscription_retry(bool retry);
+
/*
* Return the name of the logical replication worker.
*/
@@ -1046,6 +1048,9 @@ apply_handle_commit(StringInfo s)
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(commit_data.end_lsn);
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_activity(STATE_IDLE, NULL);
reset_apply_error_context_info();
}
@@ -1152,6 +1157,9 @@ apply_handle_prepare(StringInfo s)
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(prepare_data.end_lsn);
@@ -1208,6 +1216,9 @@ apply_handle_commit_prepared(StringInfo s)
store_flush_position(prepare_data.end_lsn, XactLastCommitEnd);
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(prepare_data.end_lsn);
@@ -1269,6 +1280,9 @@ apply_handle_rollback_prepared(StringInfo s)
store_flush_position(rollback_data.rollback_end_lsn, XactLastCommitEnd);
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(rollback_data.rollback_end_lsn);
@@ -1394,6 +1408,9 @@ apply_handle_stream_prepare(StringInfo s)
break;
}
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_stat(false);
/* Process any tables that are being synchronized in parallel. */
@@ -1970,6 +1987,10 @@ apply_handle_stream_abort(StringInfo s)
break;
}
+ /* Reset the retry flag. */
+ if (toplevel_xact)
+ set_subscription_retry(false);
+
reset_apply_error_context_info();
}
@@ -2252,6 +2273,9 @@ apply_handle_stream_commit(StringInfo s)
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(commit_data.end_lsn);
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_activity(STATE_IDLE, NULL);
reset_apply_error_context_info();
@@ -4348,20 +4372,28 @@ start_table_sync(XLogRecPtr *origin_startpos, char **myslotname)
}
PG_CATCH();
{
+ /*
+ * Emit the error message, and recover from the error state to an idle
+ * state
+ */
+ HOLD_INTERRUPTS();
+
+ EmitErrorReport();
+ AbortOutOfAnyTransaction();
+ FlushErrorState();
+
+ RESUME_INTERRUPTS();
+
+ /* Report the worker failed during table synchronization */
+ pgstat_report_subscription_error(MySubscription->oid, false);
+
if (MySubscription->disableonerr)
- DisableSubscriptionAndExit();
- else
- {
- /*
- * Report the worker failed during table synchronization. Abort
- * the current transaction so that the stats message is sent in an
- * idle state.
- */
- AbortOutOfAnyTransaction();
- pgstat_report_subscription_error(MySubscription->oid, false);
+ DisableSubscriptionOnError();
- PG_RE_THROW();
- }
+ /* Set the retry flag. */
+ set_subscription_retry(true);
+
+ proc_exit(0);
}
PG_END_TRY();
@@ -4386,20 +4418,27 @@ start_apply(XLogRecPtr origin_startpos)
}
PG_CATCH();
{
+ /*
+ * Emit the error message, and recover from the error state to an idle
+ * state
+ */
+ HOLD_INTERRUPTS();
+
+ EmitErrorReport();
+ AbortOutOfAnyTransaction();
+ FlushErrorState();
+
+ RESUME_INTERRUPTS();
+
+ /* Report the worker failed while applying changes */
+ pgstat_report_subscription_error(MySubscription->oid,
+ !am_tablesync_worker());
+
if (MySubscription->disableonerr)
- DisableSubscriptionAndExit();
- else
- {
- /*
- * Report the worker failed while applying changes. Abort the
- * current transaction so that the stats message is sent in an
- * idle state.
- */
- AbortOutOfAnyTransaction();
- pgstat_report_subscription_error(MySubscription->oid, !am_tablesync_worker());
+ DisableSubscriptionOnError();
- PG_RE_THROW();
- }
+ /* Set the retry flag. */
+ set_subscription_retry(true);
}
PG_END_TRY();
}
@@ -4675,39 +4714,20 @@ ApplyWorkerMain(Datum main_arg)
}
/*
- * After error recovery, disable the subscription in a new transaction
- * and exit cleanly.
+ * Disable the subscription in a new transaction.
*/
static void
-DisableSubscriptionAndExit(void)
+DisableSubscriptionOnError(void)
{
- /*
- * Emit the error message, and recover from the error state to an idle
- * state
- */
- HOLD_INTERRUPTS();
-
- EmitErrorReport();
- AbortOutOfAnyTransaction();
- FlushErrorState();
-
- RESUME_INTERRUPTS();
-
- /* Report the worker failed during either table synchronization or apply */
- pgstat_report_subscription_error(MyLogicalRepWorker->subid,
- !am_tablesync_worker());
-
/* Disable the subscription */
StartTransactionCommand();
DisableSubscription(MySubscription->oid);
CommitTransactionCommand();
- /* Notify the subscription has been disabled and exit */
+ /* Notify the subscription has been disabled */
ereport(LOG,
errmsg("subscription \"%s\" has been disabled because of an error",
MySubscription->name));
-
- proc_exit(0);
}
/*
@@ -5050,3 +5070,71 @@ get_transaction_apply_action(TransactionId xid, ParallelApplyWorkerInfo **winfo)
return TRANS_LEADER_SEND_TO_PARALLEL;
}
}
+
+/*
+ * Set subretry of pg_subscription catalog.
+ *
+ * If retry is true, subscriber is about to exit with an error. Otherwise, it
+ * means that the transaction was applied successfully.
+ */
+static void
+set_subscription_retry(bool retry)
+{
+ Relation rel;
+ HeapTuple tup;
+ bool started_tx = false;
+ bool nulls[Natts_pg_subscription];
+ bool replaces[Natts_pg_subscription];
+ Datum values[Natts_pg_subscription];
+
+ /* Fast path - if no state change then nothing to do */
+ if (MySubscription->retry == retry)
+ return;
+
+ /* Fast path - skip for parallel apply workers */
+ if (am_parallel_apply_worker())
+ return;
+
+ /* Fast path - skip set retry if no active parallel apply workers */
+ if (retry && !pa_have_active_worker())
+ return;
+
+ if (!IsTransactionState())
+ {
+ StartTransactionCommand();
+ started_tx = true;
+ }
+
+ /* Look up the subscription in the catalog */
+ rel = table_open(SubscriptionRelationId, RowExclusiveLock);
+ tup = SearchSysCacheCopy1(SUBSCRIPTIONOID,
+ ObjectIdGetDatum(MySubscription->oid));
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "subscription \"%s\" does not exist", MySubscription->name);
+
+ LockSharedObject(SubscriptionRelationId, MySubscription->oid, 0,
+ AccessShareLock);
+
+ /* Form a new tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ /* Set subretry */
+ values[Anum_pg_subscription_subretry - 1] = BoolGetDatum(retry);
+ replaces[Anum_pg_subscription_subretry - 1] = true;
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
+ replaces);
+
+ /* Update the catalog. */
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ /* Cleanup. */
+ heap_freetuple(tup);
+ table_close(rel, NoLock);
+
+ if (started_tx)
+ CommitTransactionCommand();
+}
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 2c0a969..1bb7695 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -4560,8 +4560,9 @@ getSubscriptions(Archive *fout)
ntups = PQntuples(res);
/*
- * Get subscription fields. We don't include subskiplsn in the dump as
- * after restoring the dump this value may no longer be relevant.
+ * Get subscription fields. We don't include subskiplsn and subretry in
+ * the dump as after restoring the dump this value may no longer be
+ * relevant.
*/
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index b0f2a17..8edbbca 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -88,6 +88,11 @@ CATALOG(pg_subscription,6100,SubscriptionRelationId) BKI_SHARED_RELATION BKI_ROW
bool subdisableonerr; /* True if a worker error should cause the
* subscription to be disabled */
+ bool subretry BKI_DEFAULT(f); /* True if previous change failed
+ * to be applied while there were
+ * any active parallel apply
+ * workers */
+
#ifdef CATALOG_VARLEN /* variable-length fields start here */
/* Connection string to the publisher */
text subconninfo BKI_FORCE_NOT_NULL;
@@ -131,6 +136,8 @@ typedef struct Subscription
bool disableonerr; /* Indicates if the subscription should be
* automatically disabled if a worker error
* occurs */
+ bool retry; /* Indicates if previous change failed to be
+ * applied using a parallel apply worker */
char *conninfo; /* Connection string to the publisher */
char *slotname; /* Name of the replication slot */
char *synccommit; /* Synchronous commit setting for worker */
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index 7f6a9f9..2e466e0 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -308,6 +308,8 @@ extern void pa_decr_and_wait_stream_block(void);
extern void pa_xact_finish(ParallelApplyWorkerInfo *winfo,
XLogRecPtr remote_lsn);
+extern bool pa_have_active_worker(void);
+
#define isParallelApplyWorker(worker) ((worker)->leader_pid != InvalidPid)
static inline bool
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 83d6956..4054a5f 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -74,8 +74,16 @@ sub test_streaming
'check extra columns contain local defaults');
# Test the streaming in binary mode
+ my $oldpid = $node_publisher->safe_psql('postgres',
+ "SELECT pid FROM pg_stat_replication WHERE application_name = '$appname' AND state = 'streaming';"
+ );
$node_subscriber->safe_psql('postgres',
"ALTER SUBSCRIPTION tap_sub SET (binary = on)");
+ $node_publisher->poll_query_until('postgres',
+ "SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = '$appname' AND state = 'streaming';"
+ )
+ or die
+ "Timed out while waiting for apply to restart after changing SUBSCRIPTION";
# Check the subscriber log from now on.
$offset = -s $node_subscriber->logfile;
@@ -450,6 +458,61 @@ $result =
is($result, qq(5000),
'data replicated to subscriber by serializing messages to disk');
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# ============================================================================
+# Test re-apply a failed streaming transaction using the leader apply
+# worker and apply subsequent streaming transaction using the parallel apply
+# worker after this retry succeeds.
+# ============================================================================
+
+$node_subscriber->safe_psql('postgres',
+ "CREATE UNIQUE INDEX idx_tab on test_tab_2(a)");
+
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', qq{
+BEGIN;
+INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+INSERT INTO test_tab_2 values(1);
+COMMIT;});
+
+# Check if the parallel apply worker is not started because the above
+# transaction failed to be applied.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? parallel apply workers are not used for retries/,
+ $offset);
+
+# Drop the unique index on the subscriber, now it works.
+$node_subscriber->safe_psql('postgres', "DROP INDEX idx_tab");
+
+# Wait for this streaming transaction to be applied in the apply worker.
+$node_publisher->wait_for_catchup($appname);
+
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5001), 'data replicated to subscriber after dropping index');
+
+# After successfully retrying to apply a failed streaming transaction, apply
+# the following streaming transaction using the parallel apply worker.
+
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(5001, 10000) s(i)");
+
+check_parallel_log($node_subscriber, $offset, 1, 'COMMIT');
+
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(10001),
+ 'data replicated to subscriber using the parallel apply worker');
+
$node_subscriber->stop;
$node_publisher->stop;
--
2.7.2.windows.1
[application/octet-stream] v79-0001-Add-leader_pid-to-pg_stat_subscription.patch (12.6K, ../../OS0PR01MB5716C663C85687E76672327094FD9@OS0PR01MB5716.jpnprd01.prod.outlook.com/3-v79-0001-Add-leader_pid-to-pg_stat_subscription.patch)
download | inline diff:
From 6ff8da08019e6edaabd11a763e572dcffea86da6 Mon Sep 17 00:00:00 2001
From: "houzj.fnst" <[email protected]>
Date: Thu, 6 Oct 2022 14:42:24 +0800
Subject: [PATCH v79 1/4] Add leader_pid to pg_stat_subscription
leader_pid is the process ID of the leader apply worker if this process is a
parallel apply worker. If this field is NULL, it indicates that the process is
a leader apply worker or does not participate in parallel apply, or a
synchronization worker.
The new column makes it easier to distinguish parallel apply workers from other
kinds of workers. It is implemented this way to be similar to the 'leader_pid'
column in pg_stat_activity.
---
doc/src/sgml/logical-replication.sgml | 3 +-
doc/src/sgml/monitoring.sgml | 28 ++++++++++++-----
src/backend/catalog/system_views.sql | 1 +
.../replication/logical/applyparallelworker.c | 6 ++--
src/backend/replication/logical/launcher.c | 36 ++++++++++++----------
src/include/catalog/pg_proc.dat | 6 ++--
src/include/replication/worker_internal.h | 4 +--
src/test/regress/expected/rules.out | 3 +-
8 files changed, 53 insertions(+), 34 deletions(-)
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 54f48be..f4b4e64 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1692,7 +1692,8 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
subscription. A disabled subscription or a crashed subscription will have
zero rows in this view. If the initial data synchronization of any
table is in progress, there will be additional workers for the tables
- being synchronized.
+ being synchronized. Moreover, if the streaming transaction is applied in
+ parallel, there may be additional parallel apply workers.
</para>
</sect1>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 358d2ff..9450757 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -3208,11 +3208,22 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<row>
<entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>leader_pid</structfield> <type>integer</type>
+ </para>
+ <para>
+ Process ID of the leader apply worker if this process is a parallel
+ apply worker; NULL if this process is a leader apply worker or does not
+ participate in parallel apply, or a synchronization worker
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
<structfield>relid</structfield> <type>oid</type>
</para>
<para>
- OID of the relation that the worker is synchronizing; null for the
- main apply worker
+ OID of the relation that the worker is synchronizing; NULL for the
+ leader apply worker and parallel apply workers
</para></entry>
</row>
@@ -3222,7 +3233,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Last write-ahead log location received, the initial value of
- this field being 0
+ this field being 0; NULL for parallel apply workers
</para></entry>
</row>
@@ -3231,7 +3242,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_send_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Send time of last message received from origin WAL sender
+ Send time of last message received from origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3240,7 +3252,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_receipt_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Receipt time of last message received from origin WAL sender
+ Receipt time of last message received from origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3249,7 +3262,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>latest_end_lsn</structfield> <type>pg_lsn</type>
</para>
<para>
- Last write-ahead log location reported to origin WAL sender
+ Last write-ahead log location reported to origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3259,7 +3273,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Time of last write-ahead log location reported to origin WAL
- sender
+ sender; NULL for parallel apply workers
</para></entry>
</row>
</tbody>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 447c9b9..ff63405 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -949,6 +949,7 @@ CREATE VIEW pg_stat_subscription AS
su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 2e5914d..a11b27e 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -849,7 +849,7 @@ LogicalParallelApplyLoop(shm_mq_handle *mqh)
static void
pa_shutdown(int code, Datum arg)
{
- SendProcSignal(MyLogicalRepWorker->apply_leader_pid,
+ SendProcSignal(MyLogicalRepWorker->leader_pid,
PROCSIG_PARALLEL_APPLY_MESSAGE,
InvalidBackendId);
@@ -932,7 +932,7 @@ ParallelApplyWorkerMain(Datum main_arg)
error_mqh = shm_mq_attach(mq, seg, NULL);
pq_redirect_to_shm_mq(seg, error_mqh);
- pq_set_parallel_leader(MyLogicalRepWorker->apply_leader_pid,
+ pq_set_parallel_leader(MyLogicalRepWorker->leader_pid,
InvalidBackendId);
MyLogicalRepWorker->last_send_time = MyLogicalRepWorker->last_recv_time =
@@ -950,7 +950,7 @@ ParallelApplyWorkerMain(Datum main_arg)
* The parallel apply worker doesn't need to monopolize this replication
* origin which was already acquired by its leader process.
*/
- replorigin_session_setup(originid, MyLogicalRepWorker->apply_leader_pid);
+ replorigin_session_setup(originid, MyLogicalRepWorker->leader_pid);
replorigin_session_origin = originid;
CommitTransactionCommand();
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index afb7acd..9385ada 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -410,7 +410,7 @@ retry:
worker->relstate = SUBREL_STATE_UNKNOWN;
worker->relstate_lsn = InvalidXLogRecPtr;
worker->stream_fileset = NULL;
- worker->apply_leader_pid = is_parallel_apply_worker ? MyProcPid : InvalidPid;
+ worker->leader_pid = is_parallel_apply_worker ? MyProcPid : InvalidPid;
worker->parallel_apply = is_parallel_apply_worker;
worker->last_lsn = InvalidXLogRecPtr;
TIMESTAMP_NOBEGIN(worker->last_send_time);
@@ -732,7 +732,7 @@ logicalrep_worker_cleanup(LogicalRepWorker *worker)
worker->userid = InvalidOid;
worker->subid = InvalidOid;
worker->relid = InvalidOid;
- worker->apply_leader_pid = InvalidPid;
+ worker->leader_pid = InvalidPid;
worker->parallel_apply = false;
}
@@ -1072,7 +1072,7 @@ IsLogicalLauncher(void)
Datum
pg_stat_get_subscription(PG_FUNCTION_ARGS)
{
-#define PG_STAT_GET_SUBSCRIPTION_COLS 8
+#define PG_STAT_GET_SUBSCRIPTION_COLS 9
Oid subid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
int i;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
@@ -1098,10 +1098,6 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
if (OidIsValid(subid) && worker.subid != subid)
continue;
- /* Skip if this is a parallel apply worker */
- if (isParallelApplyWorker(&worker))
- continue;
-
worker_pid = worker.proc->pid;
values[0] = ObjectIdGetDatum(worker.subid);
@@ -1110,26 +1106,32 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
else
nulls[1] = true;
values[2] = Int32GetDatum(worker_pid);
- if (XLogRecPtrIsInvalid(worker.last_lsn))
+
+ if (isParallelApplyWorker(&worker))
+ values[3] = Int32GetDatum(worker.leader_pid);
+ else
nulls[3] = true;
+
+ if (XLogRecPtrIsInvalid(worker.last_lsn))
+ nulls[4] = true;
else
- values[3] = LSNGetDatum(worker.last_lsn);
+ values[4] = LSNGetDatum(worker.last_lsn);
if (worker.last_send_time == 0)
- nulls[4] = true;
+ nulls[5] = true;
else
- values[4] = TimestampTzGetDatum(worker.last_send_time);
+ values[5] = TimestampTzGetDatum(worker.last_send_time);
if (worker.last_recv_time == 0)
- nulls[5] = true;
+ nulls[6] = true;
else
- values[5] = TimestampTzGetDatum(worker.last_recv_time);
+ values[6] = TimestampTzGetDatum(worker.last_recv_time);
if (XLogRecPtrIsInvalid(worker.reply_lsn))
- nulls[6] = true;
+ nulls[7] = true;
else
- values[6] = LSNGetDatum(worker.reply_lsn);
+ values[7] = LSNGetDatum(worker.reply_lsn);
if (worker.reply_time == 0)
- nulls[7] = true;
+ nulls[8] = true;
else
- values[7] = TimestampTzGetDatum(worker.reply_time);
+ values[8] = TimestampTzGetDatum(worker.reply_time);
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
values, nulls);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3810de7..86eb8e8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5430,9 +5430,9 @@
proname => 'pg_stat_get_subscription', prorows => '10', proisstrict => 'f',
proretset => 't', provolatile => 's', proparallel => 'r',
prorettype => 'record', proargtypes => 'oid',
- proallargtypes => '{oid,oid,oid,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
- proargmodes => '{i,o,o,o,o,o,o,o,o}',
- proargnames => '{subid,subid,relid,pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
+ proallargtypes => '{oid,oid,oid,int4,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{subid,subid,relid,pid,leader_pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
prosrc => 'pg_stat_get_subscription' },
{ oid => '2026', descr => 'statistics: current backend PID',
proname => 'pg_backend_pid', provolatile => 's', proparallel => 'r',
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index db891ee..dc87a4e 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -71,7 +71,7 @@ typedef struct LogicalRepWorker
* PID of leader apply worker if this slot is used for a parallel apply
* worker, InvalidPid otherwise.
*/
- pid_t apply_leader_pid;
+ pid_t leader_pid;
/* Indicates whether apply can be performed in parallel. */
bool parallel_apply;
@@ -303,7 +303,7 @@ extern void pa_decr_and_wait_stream_block(void);
extern void pa_xact_finish(ParallelApplyWorkerInfo *winfo,
XLogRecPtr remote_lsn);
-#define isParallelApplyWorker(worker) ((worker)->apply_leader_pid != InvalidPid)
+#define isParallelApplyWorker(worker) ((worker)->leader_pid != InvalidPid)
static inline bool
am_tablesync_worker(void)
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index fb9f936..e31b5d0 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2094,6 +2094,7 @@ pg_stat_ssl| SELECT s.pid,
pg_stat_subscription| SELECT su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
@@ -2101,7 +2102,7 @@ pg_stat_subscription| SELECT su.oid AS subid,
st.latest_end_lsn,
st.latest_end_time
FROM (pg_subscription su
- LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
+ LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, leader_pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
pg_stat_subscription_stats| SELECT ss.subid,
s.subname,
ss.apply_error_count,
--
2.7.2.windows.1
[application/octet-stream] v79-0002-Stop-extra-worker-if-GUC-was-changed.patch (4.2K, ../../OS0PR01MB5716C663C85687E76672327094FD9@OS0PR01MB5716.jpnprd01.prod.outlook.com/4-v79-0002-Stop-extra-worker-if-GUC-was-changed.patch)
download | inline diff:
From e99aaebd567db17813fe06b2c4384bde18c45ef7 Mon Sep 17 00:00:00 2001
From: sherlockcpp <[email protected]>
Date: Sat, 17 Dec 2022 20:43:21 +0800
Subject: [PATCH v79 2/4] Stop extra worker if GUC was changed
If the max_parallel_apply_workers_per_subscription is changed to a
lower value, try to stop free workers in the pool to keep the number of
workers lower than half of the max_parallel_apply_workers_per_subscription
---
.../replication/logical/applyparallelworker.c | 60 ++++++++++++++++++----
src/backend/replication/logical/worker.c | 7 +++
src/include/replication/worker_internal.h | 1 +
3 files changed, 57 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index a11b27e..4fa2b62 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -543,6 +543,25 @@ pa_find_worker(TransactionId xid)
}
/*
+ * Stop the given parallel apply worker and free the corresponding info.
+ */
+static void
+pa_stop_worker(ParallelApplyWorkerInfo *winfo)
+{
+ int slot_no;
+ uint16 generation;
+
+ SpinLockAcquire(&winfo->shared->mutex);
+ generation = winfo->shared->logicalrep_worker_generation;
+ slot_no = winfo->shared->logicalrep_worker_slot_no;
+ SpinLockRelease(&winfo->shared->mutex);
+
+ logicalrep_pa_worker_stop(slot_no, generation);
+
+ pa_free_worker_info(winfo);
+}
+
+/*
* Makes the worker available for reuse.
*
* This removes the parallel apply worker entry from the hash table so that it
@@ -577,23 +596,42 @@ pa_free_worker(ParallelApplyWorkerInfo *winfo)
list_length(ParallelApplyWorkerPool) >
(max_parallel_apply_workers_per_subscription / 2))
{
- int slot_no;
- uint16 generation;
-
- SpinLockAcquire(&winfo->shared->mutex);
- generation = winfo->shared->logicalrep_worker_generation;
- slot_no = winfo->shared->logicalrep_worker_slot_no;
- SpinLockRelease(&winfo->shared->mutex);
+ pa_stop_worker(winfo);
+ return;
+ }
- logicalrep_pa_worker_stop(slot_no, generation);
+ winfo->in_use = false;
+ winfo->serialize_changes = false;
+}
- pa_free_worker_info(winfo);
+/*
+ * Try to stop parallel apply workers that are not in use to keep the number of
+ * workers lower than half of the max_parallel_apply_workers_per_subscription.
+ */
+void
+pa_stop_idle_workers(void)
+{
+ List *active_workers;
+ ListCell *lc;
+ int max_applyworkers = max_parallel_apply_workers_per_subscription / 2;
+ if (list_length(ParallelApplyWorkerPool) <= max_applyworkers)
return;
+
+ active_workers = list_copy(ParallelApplyWorkerPool);
+
+ foreach(lc, active_workers)
+ {
+ ParallelApplyWorkerInfo *winfo = (ParallelApplyWorkerInfo *) lfirst(lc);
+
+ pa_stop_worker(winfo);
+
+ /* Recheck the number of workers. */
+ if (list_length(ParallelApplyWorkerPool) <= max_applyworkers)
+ break;
}
- winfo->in_use = false;
- winfo->serialize_changes = false;
+ list_free(active_workers);
}
/*
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 79cda39..c7be76d 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -3630,6 +3630,13 @@ LogicalRepApplyLoop(XLogRecPtr last_received)
{
ConfigReloadPending = false;
ProcessConfigFile(PGC_SIGHUP);
+
+ /*
+ * Try to stop free workers in the pool in case the
+ * max_parallel_apply_workers_per_subscription is changed to a
+ * lower value.
+ */
+ pa_stop_idle_workers();
}
if (rc & WL_TIMEOUT)
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index dc87a4e..34e5006 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -274,6 +274,7 @@ extern void set_apply_error_context_origin(char *originname);
/* Parallel apply worker setup and interactions */
extern void pa_allocate_worker(TransactionId xid);
extern ParallelApplyWorkerInfo *pa_find_worker(TransactionId xid);
+extern void pa_stop_idle_workers(void);
extern void pa_detach_all_error_mq(void);
extern bool pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes,
--
2.7.2.windows.1
[application/octet-stream] v79-0003-Add-GUC-stream_serialize_threshold-and-test-seri.patch (12.5K, ../../OS0PR01MB5716C663C85687E76672327094FD9@OS0PR01MB5716.jpnprd01.prod.outlook.com/5-v79-0003-Add-GUC-stream_serialize_threshold-and-test-seri.patch)
download | inline diff:
From 63b859a9b0d1003b4466bf118ac7cd0c899cb248 Mon Sep 17 00:00:00 2001
From: Amit Kapila <[email protected]>
Date: Mon, 2 Jan 2023 15:37:25 +0530
Subject: [PATCH v79 3/4] Add GUC stream_serialize_threshold and test
serializing messages to disk.
---
doc/src/sgml/config.sgml | 32 +++++
.../replication/logical/applyparallelworker.c | 12 ++
src/backend/replication/logical/worker.c | 9 ++
src/backend/utils/misc/guc_tables.c | 14 ++
src/include/replication/worker_internal.h | 4 +
src/test/subscription/t/015_stream.pl | 144 ++++++++++++++++++++-
6 files changed, 212 insertions(+), 3 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 77574e2..0f24410 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11683,6 +11683,38 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
+ <varlistentry id="guc-stream-serialize-threshold" xreflabel="stream_serialize_threshold">
+ <term><varname>stream_serialize_threshold</varname> (<type>integer</type>)
+ <indexterm>
+ <primary><varname>stream_serialize_threshold</varname> configuration parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Forces the leader apply worker to serialize messages to files after
+ sending specified amount of streaming chunks to the parallel apply
+ worker. Setting this to zero serialize all messages. A value of
+ <literal>-1</literal> (the default) disables this feature. This is
+ intended to test serialization to files with
+ <literal>streaming = parallel</literal>.
+ </para>
+
+ <para>
+ When logical replication subscription <literal>streaming</literal>
+ parameter is set to <literal>parallel</literal>, the leader apply worker
+ sends messages to parallel workers with a timeout. By default, the
+ leader apply worker will serialize the remaining messages to files if
+ the timeout is exceeded. If this option is set to any value other than
+ <literal>-1</literal>, serialize to files even without timeout.
+ </para>
+
+ <para>
+ This parameter can only be set in the <filename>postgresql.conf</filename>
+ file or on the server command line.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</sect1>
<sect1 id="runtime-config-short">
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 4fa2b62..777926c 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -254,6 +254,9 @@ static ParallelApplyWorkerInfo *stream_apply_worker = NULL;
/* A list to maintain subtransactions, if any. */
static List *subxactlist = NIL;
+/* GUC variable */
+int stream_serialize_threshold = -1;
+
static void pa_free_worker_info(ParallelApplyWorkerInfo *winfo);
static ParallelTransState pa_get_xact_state(ParallelApplyWorkerShared *wshared);
static PartialFileSetState pa_get_fileset_state(void);
@@ -1187,6 +1190,15 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ /* Force to serialize messages if stream_serialize_threshold is reached. */
+ if (stream_serialize_threshold != -1 &&
+ (stream_serialize_threshold == 0 ||
+ stream_serialize_threshold < parallel_stream_nchunks))
+ {
+ parallel_stream_nchunks = 0;
+ return false;
+ }
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index c7be76d..5c8ce97 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -328,6 +328,12 @@ static TransactionId stream_xid = InvalidTransactionId;
static uint32 parallel_stream_nchanges = 0;
/*
+ * The number of streaming chunks sent by leader apply worker during one
+ * streamed transaction. This is only used when stream_serialize_threshold > 0.
+ */
+uint32 parallel_stream_nchunks = 0;
+
+/*
* We enable skipping all data modification changes (INSERT, UPDATE, etc.) for
* the subscription if the remote transaction's finish LSN matches the subskiplsn.
* Once we start skipping changes, we don't stop it until we skip all changes of
@@ -1521,6 +1527,9 @@ apply_handle_stream_start(StringInfo s)
case TRANS_LEADER_SEND_TO_PARALLEL:
Assert(winfo);
+ if (stream_serialize_threshold > 0)
+ parallel_stream_nchunks++;
+
/*
* Once we start serializing the changes, the parallel apply
* worker will wait for the leader to release the stream lock
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 5025e80..15d3781 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -61,6 +61,7 @@
#include "replication/logicallauncher.h"
#include "replication/slot.h"
#include "replication/syncrep.h"
+#include "replication/worker_internal.h"
#include "storage/bufmgr.h"
#include "storage/large_object.h"
#include "storage/pg_shmem.h"
@@ -3015,6 +3016,19 @@ struct config_int ConfigureNamesInt[] =
},
{
+ {"stream_serialize_threshold", PGC_SIGHUP, DEVELOPER_OPTIONS,
+ gettext_noop("Forces the leader apply worker to serialize messages "
+ "to files after sending specified amount of streaming "
+ "chunks in streaming parallel mode."),
+ gettext_noop("A value of -1 disables this feature."),
+ GUC_NOT_IN_SAMPLE
+ },
+ &stream_serialize_threshold,
+ -1, -1, INT_MAX,
+ NULL, NULL, NULL
+ },
+
+ {
{"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
gettext_noop("Sets the amount of time to wait before forcing "
"log file rotation."),
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index 34e5006..7f6a9f9 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -225,6 +225,10 @@ extern PGDLLIMPORT LogicalRepWorker *MyLogicalRepWorker;
extern PGDLLIMPORT bool in_remote_transaction;
+extern PGDLLIMPORT int stream_serialize_threshold;
+
+extern PGDLLIMPORT uint32 parallel_stream_nchunks;
+
extern void logicalrep_worker_attach(int slot);
extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
bool only_running);
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8..83d6956 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -133,13 +133,20 @@ sub test_streaming
# Create publisher node
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
-$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_work_mem = 64kB');
+$node_publisher->append_conf(
+ 'postgresql.conf', qq(
+max_prepared_transactions = 10
+logical_decoding_work_mem = 64kB
+));
$node_publisher->start;
# Create subscriber node
my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->append_conf(
+ 'postgresql.conf', qq(
+max_prepared_transactions = 10
+));
$node_subscriber->start;
# Create some preexisting content on publisher
@@ -170,7 +177,7 @@ my $appname = 'tap_sub';
# Test using streaming mode 'on'
################################
$node_subscriber->safe_psql('postgres',
- "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (streaming = on)"
+ "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (streaming = on, two_phase = on)"
);
# Wait for initial table sync to finish
@@ -312,6 +319,137 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Test serializing messages to disk
+
+# Set stream_serialize_threshold to zero, so the messages will be serialized to disk.
+$node_subscriber->safe_psql('postgres',
+ 'ALTER SYSTEM SET stream_serialize_threshold = 0;');
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+# Serialize the COMMIT transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? opening file ".*\.changes" for streamed changes/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the PREPARE transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? opening file ".*\.changes" for streamed changes/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the ABORT top-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ ROLLBACK;
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? opening file ".*\.changes" for streamed changes/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(5001, 10000) s(i);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? opening file ".*\.changes" for streamed changes/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
$node_subscriber->stop;
$node_publisher->stop;
--
2.7.2.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-13 02:25 ` Peter Smith <[email protected]>
2023-01-13 03:36 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Peter Smith @ 2023-01-13 02:25 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
Here are my review comments for v79-0001.
======
General
1.
When Amit suggested [1] changing the name just to "leader_pid" instead
of "leader_apply_pid" I thought he was only referring to changing the
view column name, not also the internal member names of the worker
structure. Maybe it is OK anyway, but please check if that was the
intention.
======
Commit message
2.
leader_pid is the process ID of the leader apply worker if this process is a
parallel apply worker. If this field is NULL, it indicates that the process is
a leader apply worker or does not participate in parallel apply, or a
synchronization worker.
~
This text is just cut/paste from the monitoring.sgml. In a review
comment below I suggest some changes to that text, so then this commit
message should also change to be the same.
======
doc/src/sgml/monitoring.sgml
3.
<entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>leader_pid</structfield> <type>integer</type>
+ </para>
+ <para>
+ Process ID of the leader apply worker if this process is a parallel
+ apply worker; NULL if this process is a leader apply worker or does not
+ participate in parallel apply, or a synchronization worker
+ </para></entry>
I felt this change is giving too many details and ended up just
muddying the water.
E.g. Now this says basically "NULL if AAA or BBB, or CCC" but that
makes it sounds like there are 3 other things the process could be
instead of a parallel worker. But that is not not really true unless
you are making some distinction between the main "apply worker" which
is a leader versus a main apply worker which is not a leader. IMO we
should not be making any distinction at all - the leader apply worker
and the main (not leader) apply worker are one-and-the-same process.
So, I still prefer my previous suggestion (see [2] #5b]
======
src/backend/catalog/system_views.sql
4.
@@ -949,6 +949,7 @@ CREATE VIEW pg_stat_subscription AS
su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
IMO it would be very useful to have an additional "kind" attribute for
this view. This will save the user from needing to do mental
gymnastics every time just to recognise what kind of process they are
looking at.
For example, I tried this:
CREATE VIEW pg_stat_subscription AS
SELECT
su.oid AS subid,
su.subname,
CASE
WHEN st.relid IS NOT NULL THEN 'tablesync'
WHEN st.leader_pid IS NOT NULL THEN 'parallel apply'
ELSE 'leader apply'
END AS kind,
st.pid,
st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
st.last_msg_receipt_time,
st.latest_end_lsn,
st.latest_end_time
FROM pg_subscription su
LEFT JOIN pg_stat_get_subscription(NULL) st
ON (st.subid = su.oid);
and it results in much more readable output IMO:
test_sub=# select * from pg_stat_subscription;
subid | subname | kind | pid | leader_pid | relid |
received_lsn | last_msg_send_time |
last_msg_receipt_time | lat
est_end_lsn | latest_end_time
-------+---------+--------------+------+------------+-------+--------------+-------------------------------+-------------------------------+----
------------+-------------------------------
16388 | sub1 | leader apply | 5281 | | |
0/1901378 | 2023-01-13 12:39:03.984249+11 | 2023-01-13
12:39:03.986157+11 | 0/1
901378 | 2023-01-13 12:39:03.984249+11
(1 row)
Thoughts?
------
[1] Amit - https://www.postgresql.org/message-id/CAA4eK1KYUbnthSPyo4VjnhMygB0c1DZtp0XC-V2-GSETQ743ww%40mail.gma...
[2] My v78-0001 review -
https://www.postgresql.org/message-id/CAHut%2BPvA10Bp9Jaw9OS2%2BpuKHr7ry_xB3Tf2-bbv5gyxD5E_gw%40mail...
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 02:25 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-13 03:36 ` Amit Kapila <[email protected]>
2023-01-13 04:28 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-01-13 03:36 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; shveta malik <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Fri, Jan 13, 2023 at 7:56 AM Peter Smith <[email protected]> wrote:
>
> Here are my review comments for v79-0001.
>
> ======
>
> General
>
> 1.
>
> When Amit suggested [1] changing the name just to "leader_pid" instead
> of "leader_apply_pid" I thought he was only referring to changing the
> view column name, not also the internal member names of the worker
> structure. Maybe it is OK anyway, but please check if that was the
> intention.
>
Yes, that was the intention.
>
> 3.
>
> <entry role="catalog_table_entry"><para role="column_definition">
> + <structfield>leader_pid</structfield> <type>integer</type>
> + </para>
> + <para>
> + Process ID of the leader apply worker if this process is a parallel
> + apply worker; NULL if this process is a leader apply worker or does not
> + participate in parallel apply, or a synchronization worker
> + </para></entry>
>
> I felt this change is giving too many details and ended up just
> muddying the water.
>
I see that we give a similar description for other parameters as well.
For example leader_pid in pg_stat_activity, see client_dn,
client_serial in pg_stat_ssl. It is better to be consistent here and
this gives the reader a bit more information when the value is NULL
for the new column.
>
> 4.
>
> @@ -949,6 +949,7 @@ CREATE VIEW pg_stat_subscription AS
> su.oid AS subid,
> su.subname,
> st.pid,
> + st.leader_pid,
> st.relid,
> st.received_lsn,
> st.last_msg_send_time,
>
> IMO it would be very useful to have an additional "kind" attribute for
> this view. This will save the user from needing to do mental
> gymnastics every time just to recognise what kind of process they are
> looking at.
>
This could be a separate enhancement as the same should be true for
sync workers.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 02:25 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-13 03:36 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-13 04:28 ` Amit Kapila <[email protected]>
2023-01-13 05:02 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-01-13 04:28 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; shveta malik <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Fri, Jan 13, 2023 at 9:06 AM Amit Kapila <[email protected]> wrote:
>
> On Fri, Jan 13, 2023 at 7:56 AM Peter Smith <[email protected]> wrote:
> >
>
> >
> > 3.
> >
> > <entry role="catalog_table_entry"><para role="column_definition">
> > + <structfield>leader_pid</structfield> <type>integer</type>
> > + </para>
> > + <para>
> > + Process ID of the leader apply worker if this process is a parallel
> > + apply worker; NULL if this process is a leader apply worker or does not
> > + participate in parallel apply, or a synchronization worker
> > + </para></entry>
> >
> > I felt this change is giving too many details and ended up just
> > muddying the water.
> >
>
> I see that we give a similar description for other parameters as well.
> For example leader_pid in pg_stat_activity,
>
BTW, shouldn't we update leader_pid column in pg_stat_activity as well
to display apply leader PID for parallel apply workers? It will
currently display for other parallel operations like a parallel
vacuum, so I don't see a reason to not do the same for parallel apply
workers.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 02:25 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-13 03:36 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-13 04:28 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-13 05:02 ` Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Masahiko Sawada @ 2023-01-13 05:02 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Peter Smith <[email protected]>; [email protected] <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Fri, Jan 13, 2023 at 1:28 PM Amit Kapila <[email protected]> wrote:
>
> On Fri, Jan 13, 2023 at 9:06 AM Amit Kapila <[email protected]> wrote:
> >
> > On Fri, Jan 13, 2023 at 7:56 AM Peter Smith <[email protected]> wrote:
> > >
> >
> > >
> > > 3.
> > >
> > > <entry role="catalog_table_entry"><para role="column_definition">
> > > + <structfield>leader_pid</structfield> <type>integer</type>
> > > + </para>
> > > + <para>
> > > + Process ID of the leader apply worker if this process is a parallel
> > > + apply worker; NULL if this process is a leader apply worker or does not
> > > + participate in parallel apply, or a synchronization worker
> > > + </para></entry>
> > >
> > > I felt this change is giving too many details and ended up just
> > > muddying the water.
> > >
> >
> > I see that we give a similar description for other parameters as well.
> > For example leader_pid in pg_stat_activity,
> >
>
> BTW, shouldn't we update leader_pid column in pg_stat_activity as well
> to display apply leader PID for parallel apply workers? It will
> currently display for other parallel operations like a parallel
> vacuum, so I don't see a reason to not do the same for parallel apply
> workers.
+1
The parallel apply workers have different properties than the parallel
query workers since they execute different transactions and don't use
group locking but it would be a good hint for users to show the leader
and parallel apply worker processes are related. If users want to
check only parallel query workers they can use the backend_type
column.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 02:25 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-13 03:36 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-13 04:28 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-13 05:02 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-01-13 10:13 ` [email protected] <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: [email protected] @ 2023-01-13 10:13 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; Amit Kapila <[email protected]>; +Cc: Peter Smith <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Friday, January 13, 2023 1:02 PM Masahiko Sawada <[email protected]> wrote:
>
> On Fri, Jan 13, 2023 at 1:28 PM Amit Kapila <[email protected]> wrote:
> >
> > On Fri, Jan 13, 2023 at 9:06 AM Amit Kapila <[email protected]>
> wrote:
> > >
> > > On Fri, Jan 13, 2023 at 7:56 AM Peter Smith <[email protected]>
> wrote:
> > > >
> > >
> > > >
> > > > 3.
> > > >
> > > > <entry role="catalog_table_entry"><para
> > > > role="column_definition">
> > > > + <structfield>leader_pid</structfield> <type>integer</type>
> > > > + </para>
> > > > + <para>
> > > > + Process ID of the leader apply worker if this process is a parallel
> > > > + apply worker; NULL if this process is a leader apply worker or
> does not
> > > > + participate in parallel apply, or a synchronization worker
> > > > + </para></entry>
> > > >
> > > > I felt this change is giving too many details and ended up just
> > > > muddying the water.
> > > >
> > >
> > > I see that we give a similar description for other parameters as well.
> > > For example leader_pid in pg_stat_activity,
> > >
> >
> > BTW, shouldn't we update leader_pid column in pg_stat_activity as well
> > to display apply leader PID for parallel apply workers? It will
> > currently display for other parallel operations like a parallel
> > vacuum, so I don't see a reason to not do the same for parallel apply
> > workers.
>
> +1
>
> The parallel apply workers have different properties than the parallel query
> workers since they execute different transactions and don't use group locking
> but it would be a good hint for users to show the leader and parallel apply
> worker processes are related. If users want to check only parallel query workers
> they can use the backend_type column.
Agreed, and changed as suggested.
Attach the new version patch set which address the comments so far.
Best Regards,
Hou zj
Attachments:
[application/octet-stream] v80-0004-Retry-to-apply-streaming-xact-only-in-apply-work.patch (21.1K, ../../OS0PR01MB5716199216FFD4AED083BA8294C29@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v80-0004-Retry-to-apply-streaming-xact-only-in-apply-work.patch)
download | inline diff:
From 0f1b3a469291db836cee0f88c1e803c108fc6020 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Sun, 11 Dec 2022 19:16:34 +0800
Subject: [PATCH v80 4/4] Retry to apply streaming xact only in apply worker
When the subscription parameter is set streaming=parallel, the logic tries to
apply the streaming transaction using a parallel apply worker. If this
fails the parallel worker exits with an error.
In this case, retry applying the streaming transaction using the normal
streaming=on mode. This is done to avoid getting caught in a loop of the same
retry errors.
A new flag field "subretry" has been introduced to catalog "pg_subscription".
If there are any active parallel apply workers and the subscriber exits with an
error, this flag will be set true, and whenever the transaction is applied
successfully, this flag is reset false.
Now, when deciding how to apply a streaming transaction, the logic can know if
this transaction has previously failed or not (by checking the "subretry"
field).
Note: Since we add a new field 'subretry' to catalog 'pg_subscription' has been
expanded, we need bump catalog version.
---
doc/src/sgml/catalogs.sgml | 10 ++
doc/src/sgml/logical-replication.sgml | 11 +-
doc/src/sgml/ref/create_subscription.sgml | 5 +
src/backend/catalog/pg_subscription.c | 1 +
src/backend/catalog/system_views.sql | 2 +-
src/backend/commands/subscriptioncmds.c | 1 +
.../replication/logical/applyparallelworker.c | 30 ++++
src/backend/replication/logical/worker.c | 182 +++++++++++++++------
src/bin/pg_dump/pg_dump.c | 5 +-
src/include/catalog/pg_subscription.h | 7 +
src/include/replication/worker_internal.h | 2 +
src/test/subscription/t/015_stream.pl | 63 +++++++
12 files changed, 263 insertions(+), 56 deletions(-)
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index c1e4048..d918327 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -7950,6 +7950,16 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l
<row>
<entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>subretry</structfield> <type>bool</type>
+ </para>
+ <para>
+ True if previous change failed to be applied while there were any
+ active parallel apply workers, necessitating a retry.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
<structfield>subconninfo</structfield> <type>text</type>
</para>
<para>
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index f4b4e64..57e938f 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1504,12 +1504,11 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
<para>
When the streaming mode is <literal>parallel</literal>, the finish LSN of
- failed transactions may not be logged. In that case, it may be necessary to
- change the streaming mode to <literal>on</literal> or <literal>off</literal> and
- cause the same conflicts again so the finish LSN of the failed transaction will
- be written to the server log. For the usage of finish LSN, please refer to <link
- linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION ...
- SKIP</command></link>.
+ failed transactions may not be logged. In that case, the failed transaction
+ will be retried in <literal>streaming = on</literal> mode. If it fails
+ again, the finish LSN of the failed transaction will be written to the
+ server log. For the usage of finish LSN, please refer to
+ <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION ... SKIP</command></link>.
</para>
</sect1>
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
index eba72c6..decd554 100644
--- a/doc/src/sgml/ref/create_subscription.sgml
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -251,6 +251,11 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
transaction is committed. Note that if an error happens in a
parallel apply worker, the finish LSN of the remote transaction
might not be reported in the server log.
+ When applying streaming transactions, if a deadlock is detected, the
+ parallel apply worker will exit with an error. The
+ <literal>parallel</literal> mode is disregarded when retrying;
+ instead the transaction will be applied using <literal>on</literal>
+ mode.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index a56ae31..0eb5ffb 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -71,6 +71,7 @@ GetSubscription(Oid subid, bool missing_ok)
sub->stream = subform->substream;
sub->twophasestate = subform->subtwophasestate;
sub->disableonerr = subform->subdisableonerr;
+ sub->retry = subform->subretry;
/* Get conninfo */
datum = SysCacheGetAttr(SUBSCRIPTIONOID,
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index ff63405..97b145a 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1302,7 +1302,7 @@ REVOKE ALL ON pg_replication_origin_status FROM public;
REVOKE ALL ON pg_subscription FROM public;
GRANT SELECT (oid, subdbid, subskiplsn, subname, subowner, subenabled,
subbinary, substream, subtwophasestate, subdisableonerr,
- subslotname, subsynccommit, subpublications, suborigin)
+ subretry, subslotname, subsynccommit, subpublications, suborigin)
ON pg_subscription TO public;
CREATE VIEW pg_stat_subscription_stats AS
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index baff00d..b2053f7 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -636,6 +636,7 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
LOGICALREP_TWOPHASE_STATE_PENDING :
LOGICALREP_TWOPHASE_STATE_DISABLED);
values[Anum_pg_subscription_subdisableonerr - 1] = BoolGetDatum(opts.disableonerr);
+ values[Anum_pg_subscription_subretry - 1] = BoolGetDatum(false);
values[Anum_pg_subscription_subconninfo - 1] =
CStringGetTextDatum(conninfo);
if (opts.slot_name)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index cbcd8ca..275463f 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -315,6 +315,17 @@ pa_can_start(void)
if (!AllTablesyncsReady())
return false;
+ /*
+ * Don't use parallel apply workers for retries, because it is possible
+ * that a deadlock was detected the last time we tried to apply a
+ * transaction using a parallel apply worker.
+ */
+ if (MySubscription->retry)
+ {
+ elog(DEBUG1, "parallel apply workers are not used for retries");
+ return false;
+ }
+
return true;
}
@@ -1680,3 +1691,22 @@ pa_xact_finish(ParallelApplyWorkerInfo *winfo, XLogRecPtr remote_lsn)
pa_free_worker(winfo);
}
+
+/* Check if any active parallel apply workers. */
+bool
+pa_have_active_worker(void)
+{
+ ListCell *lc;
+
+ foreach(lc, ParallelApplyWorkerPool)
+ {
+ ParallelApplyWorkerInfo *tmp_winfo;
+
+ tmp_winfo = (ParallelApplyWorkerInfo *) lfirst(lc);
+
+ if (tmp_winfo->in_use)
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 5c8ce97..0c7bf67 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -394,7 +394,7 @@ static void stream_close_file(void);
static void send_feedback(XLogRecPtr recvpos, bool force, bool requestReply);
-static void DisableSubscriptionAndExit(void);
+static void DisableSubscriptionOnError(void);
static void apply_handle_commit_internal(LogicalRepCommitData *commit_data);
static void apply_handle_insert_internal(ApplyExecutionData *edata,
@@ -431,6 +431,8 @@ static inline void reset_apply_error_context_info(void);
static TransApplyAction get_transaction_apply_action(TransactionId xid,
ParallelApplyWorkerInfo **winfo);
+static void set_subscription_retry(bool retry);
+
/*
* Return the name of the logical replication worker.
*/
@@ -1046,6 +1048,9 @@ apply_handle_commit(StringInfo s)
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(commit_data.end_lsn);
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_activity(STATE_IDLE, NULL);
reset_apply_error_context_info();
}
@@ -1152,6 +1157,9 @@ apply_handle_prepare(StringInfo s)
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(prepare_data.end_lsn);
@@ -1208,6 +1216,9 @@ apply_handle_commit_prepared(StringInfo s)
store_flush_position(prepare_data.end_lsn, XactLastCommitEnd);
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(prepare_data.end_lsn);
@@ -1269,6 +1280,9 @@ apply_handle_rollback_prepared(StringInfo s)
store_flush_position(rollback_data.rollback_end_lsn, XactLastCommitEnd);
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(rollback_data.rollback_end_lsn);
@@ -1394,6 +1408,9 @@ apply_handle_stream_prepare(StringInfo s)
break;
}
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_stat(false);
/* Process any tables that are being synchronized in parallel. */
@@ -1970,6 +1987,10 @@ apply_handle_stream_abort(StringInfo s)
break;
}
+ /* Reset the retry flag. */
+ if (toplevel_xact)
+ set_subscription_retry(false);
+
reset_apply_error_context_info();
}
@@ -2252,6 +2273,9 @@ apply_handle_stream_commit(StringInfo s)
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(commit_data.end_lsn);
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_activity(STATE_IDLE, NULL);
reset_apply_error_context_info();
@@ -4348,20 +4372,28 @@ start_table_sync(XLogRecPtr *origin_startpos, char **myslotname)
}
PG_CATCH();
{
+ /*
+ * Emit the error message, and recover from the error state to an idle
+ * state
+ */
+ HOLD_INTERRUPTS();
+
+ EmitErrorReport();
+ AbortOutOfAnyTransaction();
+ FlushErrorState();
+
+ RESUME_INTERRUPTS();
+
+ /* Report the worker failed during table synchronization */
+ pgstat_report_subscription_error(MySubscription->oid, false);
+
if (MySubscription->disableonerr)
- DisableSubscriptionAndExit();
- else
- {
- /*
- * Report the worker failed during table synchronization. Abort
- * the current transaction so that the stats message is sent in an
- * idle state.
- */
- AbortOutOfAnyTransaction();
- pgstat_report_subscription_error(MySubscription->oid, false);
+ DisableSubscriptionOnError();
- PG_RE_THROW();
- }
+ /* Set the retry flag. */
+ set_subscription_retry(true);
+
+ proc_exit(0);
}
PG_END_TRY();
@@ -4386,20 +4418,27 @@ start_apply(XLogRecPtr origin_startpos)
}
PG_CATCH();
{
+ /*
+ * Emit the error message, and recover from the error state to an idle
+ * state
+ */
+ HOLD_INTERRUPTS();
+
+ EmitErrorReport();
+ AbortOutOfAnyTransaction();
+ FlushErrorState();
+
+ RESUME_INTERRUPTS();
+
+ /* Report the worker failed while applying changes */
+ pgstat_report_subscription_error(MySubscription->oid,
+ !am_tablesync_worker());
+
if (MySubscription->disableonerr)
- DisableSubscriptionAndExit();
- else
- {
- /*
- * Report the worker failed while applying changes. Abort the
- * current transaction so that the stats message is sent in an
- * idle state.
- */
- AbortOutOfAnyTransaction();
- pgstat_report_subscription_error(MySubscription->oid, !am_tablesync_worker());
+ DisableSubscriptionOnError();
- PG_RE_THROW();
- }
+ /* Set the retry flag. */
+ set_subscription_retry(true);
}
PG_END_TRY();
}
@@ -4675,39 +4714,20 @@ ApplyWorkerMain(Datum main_arg)
}
/*
- * After error recovery, disable the subscription in a new transaction
- * and exit cleanly.
+ * Disable the subscription in a new transaction.
*/
static void
-DisableSubscriptionAndExit(void)
+DisableSubscriptionOnError(void)
{
- /*
- * Emit the error message, and recover from the error state to an idle
- * state
- */
- HOLD_INTERRUPTS();
-
- EmitErrorReport();
- AbortOutOfAnyTransaction();
- FlushErrorState();
-
- RESUME_INTERRUPTS();
-
- /* Report the worker failed during either table synchronization or apply */
- pgstat_report_subscription_error(MyLogicalRepWorker->subid,
- !am_tablesync_worker());
-
/* Disable the subscription */
StartTransactionCommand();
DisableSubscription(MySubscription->oid);
CommitTransactionCommand();
- /* Notify the subscription has been disabled and exit */
+ /* Notify the subscription has been disabled */
ereport(LOG,
errmsg("subscription \"%s\" has been disabled because of an error",
MySubscription->name));
-
- proc_exit(0);
}
/*
@@ -5050,3 +5070,71 @@ get_transaction_apply_action(TransactionId xid, ParallelApplyWorkerInfo **winfo)
return TRANS_LEADER_SEND_TO_PARALLEL;
}
}
+
+/*
+ * Set subretry of pg_subscription catalog.
+ *
+ * If retry is true, subscriber is about to exit with an error. Otherwise, it
+ * means that the transaction was applied successfully.
+ */
+static void
+set_subscription_retry(bool retry)
+{
+ Relation rel;
+ HeapTuple tup;
+ bool started_tx = false;
+ bool nulls[Natts_pg_subscription];
+ bool replaces[Natts_pg_subscription];
+ Datum values[Natts_pg_subscription];
+
+ /* Fast path - if no state change then nothing to do */
+ if (MySubscription->retry == retry)
+ return;
+
+ /* Fast path - skip for parallel apply workers */
+ if (am_parallel_apply_worker())
+ return;
+
+ /* Fast path - skip set retry if no active parallel apply workers */
+ if (retry && !pa_have_active_worker())
+ return;
+
+ if (!IsTransactionState())
+ {
+ StartTransactionCommand();
+ started_tx = true;
+ }
+
+ /* Look up the subscription in the catalog */
+ rel = table_open(SubscriptionRelationId, RowExclusiveLock);
+ tup = SearchSysCacheCopy1(SUBSCRIPTIONOID,
+ ObjectIdGetDatum(MySubscription->oid));
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "subscription \"%s\" does not exist", MySubscription->name);
+
+ LockSharedObject(SubscriptionRelationId, MySubscription->oid, 0,
+ AccessShareLock);
+
+ /* Form a new tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ /* Set subretry */
+ values[Anum_pg_subscription_subretry - 1] = BoolGetDatum(retry);
+ replaces[Anum_pg_subscription_subretry - 1] = true;
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
+ replaces);
+
+ /* Update the catalog. */
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ /* Cleanup. */
+ heap_freetuple(tup);
+ table_close(rel, NoLock);
+
+ if (started_tx)
+ CommitTransactionCommand();
+}
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 2c0a969..1bb7695 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -4560,8 +4560,9 @@ getSubscriptions(Archive *fout)
ntups = PQntuples(res);
/*
- * Get subscription fields. We don't include subskiplsn in the dump as
- * after restoring the dump this value may no longer be relevant.
+ * Get subscription fields. We don't include subskiplsn and subretry in
+ * the dump as after restoring the dump this value may no longer be
+ * relevant.
*/
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index b0f2a17..8edbbca 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -88,6 +88,11 @@ CATALOG(pg_subscription,6100,SubscriptionRelationId) BKI_SHARED_RELATION BKI_ROW
bool subdisableonerr; /* True if a worker error should cause the
* subscription to be disabled */
+ bool subretry BKI_DEFAULT(f); /* True if previous change failed
+ * to be applied while there were
+ * any active parallel apply
+ * workers */
+
#ifdef CATALOG_VARLEN /* variable-length fields start here */
/* Connection string to the publisher */
text subconninfo BKI_FORCE_NOT_NULL;
@@ -131,6 +136,8 @@ typedef struct Subscription
bool disableonerr; /* Indicates if the subscription should be
* automatically disabled if a worker error
* occurs */
+ bool retry; /* Indicates if previous change failed to be
+ * applied using a parallel apply worker */
char *conninfo; /* Connection string to the publisher */
char *slotname; /* Name of the replication slot */
char *synccommit; /* Synchronous commit setting for worker */
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index 7f6a9f9..2e466e0 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -308,6 +308,8 @@ extern void pa_decr_and_wait_stream_block(void);
extern void pa_xact_finish(ParallelApplyWorkerInfo *winfo,
XLogRecPtr remote_lsn);
+extern bool pa_have_active_worker(void);
+
#define isParallelApplyWorker(worker) ((worker)->leader_pid != InvalidPid)
static inline bool
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index ddc00ab..48c4121 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -74,8 +74,16 @@ sub test_streaming
'check extra columns contain local defaults');
# Test the streaming in binary mode
+ my $oldpid = $node_publisher->safe_psql('postgres',
+ "SELECT pid FROM pg_stat_replication WHERE application_name = '$appname' AND state = 'streaming';"
+ );
$node_subscriber->safe_psql('postgres',
"ALTER SUBSCRIPTION tap_sub SET (binary = on)");
+ $node_publisher->poll_query_until('postgres',
+ "SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = '$appname' AND state = 'streaming';"
+ )
+ or die
+ "Timed out while waiting for apply to restart after changing SUBSCRIPTION";
# Check the subscriber log from now on.
$offset = -s $node_subscriber->logfile;
@@ -450,6 +458,61 @@ $result =
is($result, qq(5000),
'data replicated to subscriber by serializing messages to disk');
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# ============================================================================
+# Test re-apply a failed streaming transaction using the leader apply
+# worker and apply subsequent streaming transaction using the parallel apply
+# worker after this retry succeeds.
+# ============================================================================
+
+$node_subscriber->safe_psql('postgres',
+ "CREATE UNIQUE INDEX idx_tab on test_tab_2(a)");
+
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', qq{
+BEGIN;
+INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+INSERT INTO test_tab_2 values(1);
+COMMIT;});
+
+# Check if the parallel apply worker is not started because the above
+# transaction failed to be applied.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? parallel apply workers are not used for retries/,
+ $offset);
+
+# Drop the unique index on the subscriber, now it works.
+$node_subscriber->safe_psql('postgres', "DROP INDEX idx_tab");
+
+# Wait for this streaming transaction to be applied in the apply worker.
+$node_publisher->wait_for_catchup($appname);
+
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5001), 'data replicated to subscriber after dropping index');
+
+# After successfully retrying to apply a failed streaming transaction, apply
+# the following streaming transaction using the parallel apply worker.
+
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(5001, 10000) s(i)");
+
+check_parallel_log($node_subscriber, $offset, 1, 'COMMIT');
+
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(10001),
+ 'data replicated to subscriber using the parallel apply worker');
+
$node_subscriber->stop;
$node_publisher->stop;
--
2.7.2.windows.1
[application/octet-stream] v80-0001-Display-the-leader-apply-worker-s-PID-for-parall.patch (15.4K, ../../OS0PR01MB5716199216FFD4AED083BA8294C29@OS0PR01MB5716.jpnprd01.prod.outlook.com/3-v80-0001-Display-the-leader-apply-worker-s-PID-for-parall.patch)
download | inline diff:
From 05ec62698fd3ea685987441de73e15b5dca20a71 Mon Sep 17 00:00:00 2001
From: "houzj.fnst" <[email protected]>
Date: Thu, 6 Oct 2022 14:42:24 +0800
Subject: [PATCH v80] Display the leader apply worker's PID for parallel apply
workers in both pg_stat_subscription and pg_stat_activity
Add leader_pid to pg_stat_subscription. leader_pid is the process ID of the
leader apply worker if this process is a parallel apply worker. If this field
is NULL, it indicates that the process is a leader apply worker or a
synchronization worker. The new column makes it easier to distinguish parallel
apply workers from other kinds of workers.
Besides, update the leader_pid column in pg_stat_activity as well to display
the PID of the leader apply worker for parallel apply workers.
---
doc/src/sgml/logical-replication.sgml | 3 +-
doc/src/sgml/monitoring.sgml | 36 ++++++++----
src/backend/catalog/system_views.sql | 1 +
.../replication/logical/applyparallelworker.c | 6 +-
src/backend/replication/logical/launcher.c | 64 ++++++++++++++++------
src/backend/utils/adt/pgstatfuncs.c | 11 ++++
src/include/catalog/pg_proc.dat | 6 +-
src/include/replication/logicallauncher.h | 2 +
src/include/replication/worker_internal.h | 4 +-
src/test/regress/expected/rules.out | 3 +-
10 files changed, 99 insertions(+), 37 deletions(-)
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 54f48be..f4b4e64 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1692,7 +1692,8 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
subscription. A disabled subscription or a crashed subscription will have
zero rows in this view. If the initial data synchronization of any
table is in progress, there will be additional workers for the tables
- being synchronized.
+ being synchronized. Moreover, if the streaming transaction is applied in
+ parallel, there may be additional parallel apply workers.
</para>
</sect1>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 358d2ff..aa74307 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -743,9 +743,11 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<structfield>leader_pid</structfield> <type>integer</type>
</para>
<para>
- Process ID of the parallel group leader, if this process is a
- parallel query worker. <literal>NULL</literal> if this process is a
- parallel group leader or does not participate in parallel query.
+ Process ID of the parallel group leader if this process is a parallel
+ query worker, or process ID of the leader apply worker if this process
+ is a parallel apply worker. <literal>NULL</literal> indicates that this
+ process is a parallel group leader or leader apply worker, or does not
+ participate in any parallel job
</para></entry>
</row>
@@ -3208,11 +3210,22 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<row>
<entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>leader_pid</structfield> <type>integer</type>
+ </para>
+ <para>
+ Process ID of the leader apply worker if this process is a parallel
+ apply worker; NULL if this process is a leader apply worker or a
+ synchronization worker
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
<structfield>relid</structfield> <type>oid</type>
</para>
<para>
- OID of the relation that the worker is synchronizing; null for the
- main apply worker
+ OID of the relation that the worker is synchronizing; NULL for the
+ leader apply worker and parallel apply workers
</para></entry>
</row>
@@ -3222,7 +3235,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Last write-ahead log location received, the initial value of
- this field being 0
+ this field being 0; NULL for parallel apply workers
</para></entry>
</row>
@@ -3231,7 +3244,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_send_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Send time of last message received from origin WAL sender
+ Send time of last message received from origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3240,7 +3254,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_receipt_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Receipt time of last message received from origin WAL sender
+ Receipt time of last message received from origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3249,7 +3264,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>latest_end_lsn</structfield> <type>pg_lsn</type>
</para>
<para>
- Last write-ahead log location reported to origin WAL sender
+ Last write-ahead log location reported to origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3259,7 +3275,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Time of last write-ahead log location reported to origin WAL
- sender
+ sender; NULL for parallel apply workers
</para></entry>
</row>
</tbody>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 447c9b9..ff63405 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -949,6 +949,7 @@ CREATE VIEW pg_stat_subscription AS
su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 2e5914d..a11b27e 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -849,7 +849,7 @@ LogicalParallelApplyLoop(shm_mq_handle *mqh)
static void
pa_shutdown(int code, Datum arg)
{
- SendProcSignal(MyLogicalRepWorker->apply_leader_pid,
+ SendProcSignal(MyLogicalRepWorker->leader_pid,
PROCSIG_PARALLEL_APPLY_MESSAGE,
InvalidBackendId);
@@ -932,7 +932,7 @@ ParallelApplyWorkerMain(Datum main_arg)
error_mqh = shm_mq_attach(mq, seg, NULL);
pq_redirect_to_shm_mq(seg, error_mqh);
- pq_set_parallel_leader(MyLogicalRepWorker->apply_leader_pid,
+ pq_set_parallel_leader(MyLogicalRepWorker->leader_pid,
InvalidBackendId);
MyLogicalRepWorker->last_send_time = MyLogicalRepWorker->last_recv_time =
@@ -950,7 +950,7 @@ ParallelApplyWorkerMain(Datum main_arg)
* The parallel apply worker doesn't need to monopolize this replication
* origin which was already acquired by its leader process.
*/
- replorigin_session_setup(originid, MyLogicalRepWorker->apply_leader_pid);
+ replorigin_session_setup(originid, MyLogicalRepWorker->leader_pid);
replorigin_session_origin = originid;
CommitTransactionCommand();
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index afb7acd..5fdbb74 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -410,7 +410,7 @@ retry:
worker->relstate = SUBREL_STATE_UNKNOWN;
worker->relstate_lsn = InvalidXLogRecPtr;
worker->stream_fileset = NULL;
- worker->apply_leader_pid = is_parallel_apply_worker ? MyProcPid : InvalidPid;
+ worker->leader_pid = is_parallel_apply_worker ? MyProcPid : InvalidPid;
worker->parallel_apply = is_parallel_apply_worker;
worker->last_lsn = InvalidXLogRecPtr;
TIMESTAMP_NOBEGIN(worker->last_send_time);
@@ -732,7 +732,7 @@ logicalrep_worker_cleanup(LogicalRepWorker *worker)
worker->userid = InvalidOid;
worker->subid = InvalidOid;
worker->relid = InvalidOid;
- worker->apply_leader_pid = InvalidPid;
+ worker->leader_pid = InvalidPid;
worker->parallel_apply = false;
}
@@ -1067,12 +1067,40 @@ IsLogicalLauncher(void)
}
/*
+ * Return the pid of the leader apply worker if the given pid is the pid of a
+ * parallel apply worker, otherwise return 0.
+ */
+pid_t
+GetLogicalLeaderApplyWorker(pid_t pid)
+{
+ int leader_pid = 0;
+ int i;
+
+ LWLockAcquire(LogicalRepWorkerLock, LW_EXCLUSIVE);
+
+ for (i = 0; i < max_logical_replication_workers; i++)
+ {
+ LogicalRepWorker *w = &LogicalRepCtx->workers[i];
+
+ if (isParallelApplyWorker(w) && w->proc && pid == w->proc->pid)
+ {
+ leader_pid = w->leader_pid;
+ break;
+ }
+ }
+
+ LWLockRelease(LogicalRepWorkerLock);
+
+ return leader_pid;
+}
+
+/*
* Returns state of the subscriptions.
*/
Datum
pg_stat_get_subscription(PG_FUNCTION_ARGS)
{
-#define PG_STAT_GET_SUBSCRIPTION_COLS 8
+#define PG_STAT_GET_SUBSCRIPTION_COLS 9
Oid subid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
int i;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
@@ -1098,10 +1126,6 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
if (OidIsValid(subid) && worker.subid != subid)
continue;
- /* Skip if this is a parallel apply worker */
- if (isParallelApplyWorker(&worker))
- continue;
-
worker_pid = worker.proc->pid;
values[0] = ObjectIdGetDatum(worker.subid);
@@ -1110,26 +1134,32 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
else
nulls[1] = true;
values[2] = Int32GetDatum(worker_pid);
- if (XLogRecPtrIsInvalid(worker.last_lsn))
+
+ if (isParallelApplyWorker(&worker))
+ values[3] = Int32GetDatum(worker.leader_pid);
+ else
nulls[3] = true;
+
+ if (XLogRecPtrIsInvalid(worker.last_lsn))
+ nulls[4] = true;
else
- values[3] = LSNGetDatum(worker.last_lsn);
+ values[4] = LSNGetDatum(worker.last_lsn);
if (worker.last_send_time == 0)
- nulls[4] = true;
+ nulls[5] = true;
else
- values[4] = TimestampTzGetDatum(worker.last_send_time);
+ values[5] = TimestampTzGetDatum(worker.last_send_time);
if (worker.last_recv_time == 0)
- nulls[5] = true;
+ nulls[6] = true;
else
- values[5] = TimestampTzGetDatum(worker.last_recv_time);
+ values[6] = TimestampTzGetDatum(worker.last_recv_time);
if (XLogRecPtrIsInvalid(worker.reply_lsn))
- nulls[6] = true;
+ nulls[7] = true;
else
- values[6] = LSNGetDatum(worker.reply_lsn);
+ values[7] = LSNGetDatum(worker.reply_lsn);
if (worker.reply_time == 0)
- nulls[7] = true;
+ nulls[8] = true;
else
- values[7] = TimestampTzGetDatum(worker.reply_time);
+ values[8] = TimestampTzGetDatum(worker.reply_time);
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
values, nulls);
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 6cddd74..09e6f9d 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -25,6 +25,7 @@
#include "pgstat.h"
#include "postmaster/bgworker_internals.h"
#include "postmaster/postmaster.h"
+#include "replication/logicallauncher.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/acl.h"
@@ -434,6 +435,16 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
values[28] = Int32GetDatum(leader->pid);
nulls[28] = false;
}
+ else
+ {
+ int leader_pid = GetLogicalLeaderApplyWorker(beentry->st_procpid);
+
+ if (leader_pid)
+ {
+ values[28] = Int32GetDatum(leader_pid);
+ nulls[28] = false;
+ }
+ }
}
if (wait_event_type)
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3810de7..86eb8e8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5430,9 +5430,9 @@
proname => 'pg_stat_get_subscription', prorows => '10', proisstrict => 'f',
proretset => 't', provolatile => 's', proparallel => 'r',
prorettype => 'record', proargtypes => 'oid',
- proallargtypes => '{oid,oid,oid,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
- proargmodes => '{i,o,o,o,o,o,o,o,o}',
- proargnames => '{subid,subid,relid,pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
+ proallargtypes => '{oid,oid,oid,int4,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{subid,subid,relid,pid,leader_pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
prosrc => 'pg_stat_get_subscription' },
{ oid => '2026', descr => 'statistics: current backend PID',
proname => 'pg_backend_pid', provolatile => 's', proparallel => 'r',
diff --git a/src/include/replication/logicallauncher.h b/src/include/replication/logicallauncher.h
index c85593a..c3871e1 100644
--- a/src/include/replication/logicallauncher.h
+++ b/src/include/replication/logicallauncher.h
@@ -27,4 +27,6 @@ extern void AtEOXact_ApplyLauncher(bool isCommit);
extern bool IsLogicalLauncher(void);
+extern pid_t GetLogicalLeaderApplyWorker(pid_t pid);
+
#endif /* LOGICALLAUNCHER_H */
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index db891ee..dc87a4e 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -71,7 +71,7 @@ typedef struct LogicalRepWorker
* PID of leader apply worker if this slot is used for a parallel apply
* worker, InvalidPid otherwise.
*/
- pid_t apply_leader_pid;
+ pid_t leader_pid;
/* Indicates whether apply can be performed in parallel. */
bool parallel_apply;
@@ -303,7 +303,7 @@ extern void pa_decr_and_wait_stream_block(void);
extern void pa_xact_finish(ParallelApplyWorkerInfo *winfo,
XLogRecPtr remote_lsn);
-#define isParallelApplyWorker(worker) ((worker)->apply_leader_pid != InvalidPid)
+#define isParallelApplyWorker(worker) ((worker)->leader_pid != InvalidPid)
static inline bool
am_tablesync_worker(void)
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index fb9f936..e31b5d0 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2094,6 +2094,7 @@ pg_stat_ssl| SELECT s.pid,
pg_stat_subscription| SELECT su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
@@ -2101,7 +2102,7 @@ pg_stat_subscription| SELECT su.oid AS subid,
st.latest_end_lsn,
st.latest_end_time
FROM (pg_subscription su
- LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
+ LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, leader_pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
pg_stat_subscription_stats| SELECT ss.subid,
s.subname,
ss.apply_error_count,
--
2.7.2.windows.1
[application/octet-stream] v80-0002-Stop-extra-worker-if-GUC-was-changed.patch (4.2K, ../../OS0PR01MB5716199216FFD4AED083BA8294C29@OS0PR01MB5716.jpnprd01.prod.outlook.com/4-v80-0002-Stop-extra-worker-if-GUC-was-changed.patch)
download | inline diff:
From 2cdb78321165278adaa0921354e15369247e2ebc Mon Sep 17 00:00:00 2001
From: sherlockcpp <[email protected]>
Date: Sat, 17 Dec 2022 20:43:21 +0800
Subject: [PATCH v80 2/4] Stop extra worker if GUC was changed
If the max_parallel_apply_workers_per_subscription is changed to a
lower value, try to stop free workers in the pool to keep the number of
workers lower than half of the max_parallel_apply_workers_per_subscription
---
.../replication/logical/applyparallelworker.c | 63 ++++++++++++++++++----
src/backend/replication/logical/worker.c | 7 +++
src/include/replication/worker_internal.h | 1 +
3 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index a11b27e..6255e7e 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -543,6 +543,25 @@ pa_find_worker(TransactionId xid)
}
/*
+ * Stop the given parallel apply worker and free the corresponding info.
+ */
+static void
+pa_stop_worker(ParallelApplyWorkerInfo *winfo)
+{
+ int slot_no;
+ uint16 generation;
+
+ SpinLockAcquire(&winfo->shared->mutex);
+ generation = winfo->shared->logicalrep_worker_generation;
+ slot_no = winfo->shared->logicalrep_worker_slot_no;
+ SpinLockRelease(&winfo->shared->mutex);
+
+ logicalrep_pa_worker_stop(slot_no, generation);
+
+ pa_free_worker_info(winfo);
+}
+
+/*
* Makes the worker available for reuse.
*
* This removes the parallel apply worker entry from the hash table so that it
@@ -577,23 +596,45 @@ pa_free_worker(ParallelApplyWorkerInfo *winfo)
list_length(ParallelApplyWorkerPool) >
(max_parallel_apply_workers_per_subscription / 2))
{
- int slot_no;
- uint16 generation;
-
- SpinLockAcquire(&winfo->shared->mutex);
- generation = winfo->shared->logicalrep_worker_generation;
- slot_no = winfo->shared->logicalrep_worker_slot_no;
- SpinLockRelease(&winfo->shared->mutex);
+ pa_stop_worker(winfo);
+ return;
+ }
- logicalrep_pa_worker_stop(slot_no, generation);
+ winfo->in_use = false;
+ winfo->serialize_changes = false;
+}
- pa_free_worker_info(winfo);
+/*
+ * Try to stop parallel apply workers that are not in use to keep the number of
+ * workers lower than half of the max_parallel_apply_workers_per_subscription.
+ */
+void
+pa_stop_idle_workers(void)
+{
+ List *active_workers;
+ ListCell *lc;
+ int max_applyworkers = max_parallel_apply_workers_per_subscription / 2;
+ if (list_length(ParallelApplyWorkerPool) <= max_applyworkers)
return;
+
+ active_workers = list_copy(ParallelApplyWorkerPool);
+
+ foreach(lc, active_workers)
+ {
+ ParallelApplyWorkerInfo *winfo = (ParallelApplyWorkerInfo *) lfirst(lc);
+
+ if (winfo->in_use)
+ continue;
+
+ pa_stop_worker(winfo);
+
+ /* Recheck the number of workers. */
+ if (list_length(ParallelApplyWorkerPool) <= max_applyworkers)
+ break;
}
- winfo->in_use = false;
- winfo->serialize_changes = false;
+ list_free(active_workers);
}
/*
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 79cda39..c7be76d 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -3630,6 +3630,13 @@ LogicalRepApplyLoop(XLogRecPtr last_received)
{
ConfigReloadPending = false;
ProcessConfigFile(PGC_SIGHUP);
+
+ /*
+ * Try to stop free workers in the pool in case the
+ * max_parallel_apply_workers_per_subscription is changed to a
+ * lower value.
+ */
+ pa_stop_idle_workers();
}
if (rc & WL_TIMEOUT)
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index dc87a4e..34e5006 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -274,6 +274,7 @@ extern void set_apply_error_context_origin(char *originname);
/* Parallel apply worker setup and interactions */
extern void pa_allocate_worker(TransactionId xid);
extern ParallelApplyWorkerInfo *pa_find_worker(TransactionId xid);
+extern void pa_stop_idle_workers(void);
extern void pa_detach_all_error_mq(void);
extern bool pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes,
--
2.7.2.windows.1
[application/octet-stream] v80-0003-Add-GUC-stream_serialize_threshold-and-test-seri.patch (13.6K, ../../OS0PR01MB5716199216FFD4AED083BA8294C29@OS0PR01MB5716.jpnprd01.prod.outlook.com/5-v80-0003-Add-GUC-stream_serialize_threshold-and-test-seri.patch)
download | inline diff:
From 3f822083f67fb1129a29466e4aa31af48a387932 Mon Sep 17 00:00:00 2001
From: Amit Kapila <[email protected]>
Date: Mon, 2 Jan 2023 15:37:25 +0530
Subject: [PATCH v80 3/4] Add GUC stream_serialize_threshold and test
serializing messages to disk.
---
doc/src/sgml/config.sgml | 32 +++++
.../replication/logical/applyparallelworker.c | 21 ++-
src/backend/replication/logical/worker.c | 9 ++
src/backend/utils/misc/guc_tables.c | 14 ++
src/include/replication/worker_internal.h | 4 +
src/test/subscription/t/015_stream.pl | 144 ++++++++++++++++++++-
6 files changed, 216 insertions(+), 8 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 77574e2..0f24410 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11683,6 +11683,38 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
+ <varlistentry id="guc-stream-serialize-threshold" xreflabel="stream_serialize_threshold">
+ <term><varname>stream_serialize_threshold</varname> (<type>integer</type>)
+ <indexterm>
+ <primary><varname>stream_serialize_threshold</varname> configuration parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Forces the leader apply worker to serialize messages to files after
+ sending specified amount of streaming chunks to the parallel apply
+ worker. Setting this to zero serialize all messages. A value of
+ <literal>-1</literal> (the default) disables this feature. This is
+ intended to test serialization to files with
+ <literal>streaming = parallel</literal>.
+ </para>
+
+ <para>
+ When logical replication subscription <literal>streaming</literal>
+ parameter is set to <literal>parallel</literal>, the leader apply worker
+ sends messages to parallel workers with a timeout. By default, the
+ leader apply worker will serialize the remaining messages to files if
+ the timeout is exceeded. If this option is set to any value other than
+ <literal>-1</literal>, serialize to files even without timeout.
+ </para>
+
+ <para>
+ This parameter can only be set in the <filename>postgresql.conf</filename>
+ file or on the server command line.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</sect1>
<sect1 id="runtime-config-short">
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 6255e7e..cbcd8ca 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -254,6 +254,9 @@ static ParallelApplyWorkerInfo *stream_apply_worker = NULL;
/* A list to maintain subtransactions, if any. */
static List *subxactlist = NIL;
+/* GUC variable */
+int stream_serialize_threshold = -1;
+
static void pa_free_worker_info(ParallelApplyWorkerInfo *winfo);
static ParallelTransState pa_get_xact_state(ParallelApplyWorkerShared *wshared);
static PartialFileSetState pa_get_fileset_state(void);
@@ -1190,6 +1193,12 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ /* Force to serialize messages if stream_serialize_threshold is reached. */
+ if (stream_serialize_threshold != -1 &&
+ (stream_serialize_threshold == 0 ||
+ stream_serialize_threshold < parallel_stream_nchunks))
+ return false;
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
@@ -1228,12 +1237,7 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
startTime = GetCurrentTimestamp();
else if (TimestampDifferenceExceeds(startTime, GetCurrentTimestamp(),
SHM_SEND_TIMEOUT_MS))
- {
- ereport(LOG,
- (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
- winfo->shared->xid)));
return false;
- }
}
}
@@ -1247,6 +1251,13 @@ void
pa_switch_to_partial_serialize(ParallelApplyWorkerInfo *winfo,
bool stream_locked)
{
+ /* Reset parallel_stream_nchunks. */
+ parallel_stream_nchunks = 0;
+
+ ereport(LOG,
+ (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
+ winfo->shared->xid)));
+
/*
* The parallel apply worker could be stuck for some reason (say waiting
* on some lock by other backend), so stop trying to send data directly to
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index c7be76d..5c8ce97 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -328,6 +328,12 @@ static TransactionId stream_xid = InvalidTransactionId;
static uint32 parallel_stream_nchanges = 0;
/*
+ * The number of streaming chunks sent by leader apply worker during one
+ * streamed transaction. This is only used when stream_serialize_threshold > 0.
+ */
+uint32 parallel_stream_nchunks = 0;
+
+/*
* We enable skipping all data modification changes (INSERT, UPDATE, etc.) for
* the subscription if the remote transaction's finish LSN matches the subskiplsn.
* Once we start skipping changes, we don't stop it until we skip all changes of
@@ -1521,6 +1527,9 @@ apply_handle_stream_start(StringInfo s)
case TRANS_LEADER_SEND_TO_PARALLEL:
Assert(winfo);
+ if (stream_serialize_threshold > 0)
+ parallel_stream_nchunks++;
+
/*
* Once we start serializing the changes, the parallel apply
* worker will wait for the leader to release the stream lock
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 5025e80..15d3781 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -61,6 +61,7 @@
#include "replication/logicallauncher.h"
#include "replication/slot.h"
#include "replication/syncrep.h"
+#include "replication/worker_internal.h"
#include "storage/bufmgr.h"
#include "storage/large_object.h"
#include "storage/pg_shmem.h"
@@ -3015,6 +3016,19 @@ struct config_int ConfigureNamesInt[] =
},
{
+ {"stream_serialize_threshold", PGC_SIGHUP, DEVELOPER_OPTIONS,
+ gettext_noop("Forces the leader apply worker to serialize messages "
+ "to files after sending specified amount of streaming "
+ "chunks in streaming parallel mode."),
+ gettext_noop("A value of -1 disables this feature."),
+ GUC_NOT_IN_SAMPLE
+ },
+ &stream_serialize_threshold,
+ -1, -1, INT_MAX,
+ NULL, NULL, NULL
+ },
+
+ {
{"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
gettext_noop("Sets the amount of time to wait before forcing "
"log file rotation."),
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index 34e5006..7f6a9f9 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -225,6 +225,10 @@ extern PGDLLIMPORT LogicalRepWorker *MyLogicalRepWorker;
extern PGDLLIMPORT bool in_remote_transaction;
+extern PGDLLIMPORT int stream_serialize_threshold;
+
+extern PGDLLIMPORT uint32 parallel_stream_nchunks;
+
extern void logicalrep_worker_attach(int slot);
extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
bool only_running);
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8..ddc00ab 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -133,13 +133,20 @@ sub test_streaming
# Create publisher node
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
-$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_work_mem = 64kB');
+$node_publisher->append_conf(
+ 'postgresql.conf', qq(
+max_prepared_transactions = 10
+logical_decoding_work_mem = 64kB
+));
$node_publisher->start;
# Create subscriber node
my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->append_conf(
+ 'postgresql.conf', qq(
+max_prepared_transactions = 10
+));
$node_subscriber->start;
# Create some preexisting content on publisher
@@ -170,7 +177,7 @@ my $appname = 'tap_sub';
# Test using streaming mode 'on'
################################
$node_subscriber->safe_psql('postgres',
- "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (streaming = on)"
+ "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (streaming = on, two_phase = on)"
);
# Wait for initial table sync to finish
@@ -312,6 +319,137 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Test serializing messages to disk
+
+# Set stream_serialize_threshold to zero, so the messages will be serialized to disk.
+$node_subscriber->safe_psql('postgres',
+ 'ALTER SYSTEM SET stream_serialize_threshold = 0;');
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+# Serialize the COMMIT transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the PREPARE transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the ABORT top-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ ROLLBACK;
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(5001, 10000) s(i);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
$node_subscriber->stop;
$node_publisher->stop;
--
2.7.2.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-13 05:43 ` Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Masahiko Sawada @ 2023-01-13 05:43 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Thu, Jan 12, 2023 at 9:34 PM [email protected]
<[email protected]> wrote:
>
> On Thursday, January 12, 2023 7:08 PM Amit Kapila <[email protected]> wrote:
> >
> > On Thu, Jan 12, 2023 at 4:21 PM shveta malik <[email protected]> wrote:
> > >
> > > On Thu, Jan 12, 2023 at 10:34 AM Amit Kapila <[email protected]>
> > wrote:
> > > >
> > > > On Thu, Jan 12, 2023 at 9:54 AM Peter Smith <[email protected]>
> > wrote:
> > > > >
> > > > >
> > > > > doc/src/sgml/monitoring.sgml
> > > > >
> > > > > 5. pg_stat_subscription
> > > > >
> > > > > @@ -3198,11 +3198,22 @@ SELECT pid, wait_event_type, wait_event
> > > > > FROM pg_stat_activity WHERE wait_event i
> > > > >
> > > > > <row>
> > > > > <entry role="catalog_table_entry"><para
> > > > > role="column_definition">
> > > > > + <structfield>apply_leader_pid</structfield>
> > <type>integer</type>
> > > > > + </para>
> > > > > + <para>
> > > > > + Process ID of the leader apply worker, if this process is a apply
> > > > > + parallel worker. NULL if this process is a leader apply worker or a
> > > > > + synchronization worker.
> > > > > + </para></entry>
> > > > > + </row>
> > > > > +
> > > > > + <row>
> > > > > + <entry role="catalog_table_entry"><para
> > > > > + role="column_definition">
> > > > > <structfield>relid</structfield> <type>oid</type>
> > > > > </para>
> > > > > <para>
> > > > > OID of the relation that the worker is synchronizing; null for the
> > > > > - main apply worker
> > > > > + main apply worker and the parallel apply worker
> > > > > </para></entry>
> > > > > </row>
> > > > >
> > > > > 5a.
> > > > >
> > > > > (Same as general comment #1 about terminology)
> > > > >
> > > > > "apply_leader_pid" --> "leader_apply_pid"
> > > > >
> > > >
> > > > How about naming this as just leader_pid? I think it could be
> > > > helpful in the future if we decide to parallelize initial sync (aka
> > > > parallel
> > > > copy) because then we could use this for the leader PID of parallel
> > > > sync workers as well.
> > > >
> > > > --
> > >
> > > I still prefer leader_apply_pid.
> > > leader_pid does not tell which 'operation' it belongs to. 'apply'
> > > gives the clarity that it is apply related process.
> > >
> >
> > But then do you suggest that tomorrow if we allow parallel sync workers then
> > we have a separate column leader_sync_pid? I think that doesn't sound like a
> > good idea and moreover one can refer to docs for clarification.
>
> I agree that leader_pid would be better not only for future parallel copy sync feature,
> but also it's more consistent with the leader_pid column in pg_stat_activity.
>
> And here is the version patch which addressed Peter's comments and renamed all
> the related stuff to leader_pid.
Here are two comments on v79-0003 patch.
+ /* Force to serialize messages if stream_serialize_threshold
is reached. */
+ if (stream_serialize_threshold != -1 &&
+ (stream_serialize_threshold == 0 ||
+ stream_serialize_threshold < parallel_stream_nchunks))
+ {
+ parallel_stream_nchunks = 0;
+ return false;
+ }
I think it would be better if we show the log message ""logical
replication apply worker will serialize the remaining changes of
remote transaction %u to a file" even in stream_serialize_threshold
case.
IIUC parallel_stream_nchunks won't be reset if pa_send_data() failed
due to the timeout.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-01-13 10:13 ` [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: [email protected] @ 2023-01-13 10:13 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Friday, January 13, 2023 1:43 PM Masahiko Sawada <[email protected]> wrote:
> On Thu, Jan 12, 2023 at 9:34 PM [email protected]
> <[email protected]> wrote:
> >
> > On Thursday, January 12, 2023 7:08 PM Amit Kapila
> <[email protected]> wrote:
> > >
> > > On Thu, Jan 12, 2023 at 4:21 PM shveta malik <[email protected]>
> wrote:
> > > >
> > > > On Thu, Jan 12, 2023 at 10:34 AM Amit Kapila
> > > > <[email protected]>
> > > wrote:
> > > > >
> > > > > On Thu, Jan 12, 2023 at 9:54 AM Peter Smith
> > > > > <[email protected]>
> > > wrote:
> > > > > >
> > > > > >
> > > > > > doc/src/sgml/monitoring.sgml
> > > > > >
> > > > > > 5. pg_stat_subscription
> > > > > >
> > > > > > @@ -3198,11 +3198,22 @@ SELECT pid, wait_event_type,
> > > > > > wait_event FROM pg_stat_activity WHERE wait_event i
> > > > > >
> > > > > > <row>
> > > > > > <entry role="catalog_table_entry"><para
> > > > > > role="column_definition">
> > > > > > + <structfield>apply_leader_pid</structfield>
> > > <type>integer</type>
> > > > > > + </para>
> > > > > > + <para>
> > > > > > + Process ID of the leader apply worker, if this process is a
> apply
> > > > > > + parallel worker. NULL if this process is a leader apply worker
> or a
> > > > > > + synchronization worker.
> > > > > > + </para></entry>
> > > > > > + </row>
> > > > > > +
> > > > > > + <row>
> > > > > > + <entry role="catalog_table_entry"><para
> > > > > > + role="column_definition">
> > > > > > <structfield>relid</structfield> <type>oid</type>
> > > > > > </para>
> > > > > > <para>
> > > > > > OID of the relation that the worker is synchronizing; null for
> the
> > > > > > - main apply worker
> > > > > > + main apply worker and the parallel apply worker
> > > > > > </para></entry>
> > > > > > </row>
> > > > > >
> > > > > > 5a.
> > > > > >
> > > > > > (Same as general comment #1 about terminology)
> > > > > >
> > > > > > "apply_leader_pid" --> "leader_apply_pid"
> > > > > >
> > > > >
> > > > > How about naming this as just leader_pid? I think it could be
> > > > > helpful in the future if we decide to parallelize initial sync
> > > > > (aka parallel
> > > > > copy) because then we could use this for the leader PID of
> > > > > parallel sync workers as well.
> > > > >
> > > > > --
> > > >
> > > > I still prefer leader_apply_pid.
> > > > leader_pid does not tell which 'operation' it belongs to. 'apply'
> > > > gives the clarity that it is apply related process.
> > > >
> > >
> > > But then do you suggest that tomorrow if we allow parallel sync
> > > workers then we have a separate column leader_sync_pid? I think that
> > > doesn't sound like a good idea and moreover one can refer to docs for
> clarification.
> >
> > I agree that leader_pid would be better not only for future parallel
> > copy sync feature, but also it's more consistent with the leader_pid column in
> pg_stat_activity.
> >
> > And here is the version patch which addressed Peter's comments and
> > renamed all the related stuff to leader_pid.
>
> Here are two comments on v79-0003 patch.
Thanks for the comments.
>
> + /* Force to serialize messages if stream_serialize_threshold
> is reached. */
> + if (stream_serialize_threshold != -1 &&
> + (stream_serialize_threshold == 0 ||
> + stream_serialize_threshold < parallel_stream_nchunks))
> + {
> + parallel_stream_nchunks = 0;
> + return false;
> + }
>
> I think it would be better if we show the log message ""logical replication apply
> worker will serialize the remaining changes of remote transaction %u to a file"
> even in stream_serialize_threshold case.
Agreed and changed.
>
> IIUC parallel_stream_nchunks won't be reset if pa_send_data() failed due to the
> timeout.
Changed.
Best Regards,
Hou zj
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-14 11:47 ` Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-01-14 11:47 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; shveta malik <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Fri, Jan 13, 2023 at 3:44 PM [email protected]
<[email protected]> wrote:
>
> On Friday, January 13, 2023 1:43 PM Masahiko Sawada <[email protected]> wrote:
> > On Thu, Jan 12, 2023 at 9:34 PM [email protected]
> > <[email protected]> wrote:
In GetLogicalLeaderApplyWorker(), we can use shared lock instead
exclusive as we are just reading the workers array. Also, the function
name looks a bit odd to me, so I changed it to
GetLeaderApplyWorkerPid(). Also, it is better to use InvalidPid
instead of 0 when there is no valid value for leader_pid in
GetLeaderApplyWorkerPid(). Apart from that, I have made minor changes
in the comments, docs, and commit message. I am planning to push this
next week by Tuesday unless you or others have any major comments.
--
With Regards,
Amit Kapila.
Attachments:
[application/octet-stream] v81-0001-Display-the-leader-apply-worker-s-PID-for-parall.patch (15.7K, ../../CAA4eK1LA4k6=Z6cR-4b8uBT8dbE6yUS+c=0z9EiCAqOkL3S1BA@mail.gmail.com/2-v81-0001-Display-the-leader-apply-worker-s-PID-for-parall.patch)
download | inline diff:
From b9b664ac167d4f96aa75ab2f9d2e9fce66efe946 Mon Sep 17 00:00:00 2001
From: "houzj.fnst" <[email protected]>
Date: Thu, 6 Oct 2022 14:42:24 +0800
Subject: [PATCH v81] Display the leader apply worker's PID for parallel apply
workers.
Add leader_pid to pg_stat_subscription. leader_pid is the process ID of
the leader apply worker if this process is a parallel apply worker. If
this field is NULL, it indicates that the process is a leader apply
worker or a synchronization worker. The new column makes it easier to
distinguish parallel apply workers from other kinds of workers and helps
to identify the leader for the parallel workers corresponding to a
particular subscription.
Additionally, update the leader_pid column in pg_stat_activity as well to
display the PID of the leader apply worker for parallel apply workers.
Author: Hou Zhijie
Reviewed-by: Peter Smith, Sawada Masahiko, Amit Kapila
Discussion: https://postgr.es/m/CAA4eK1+wyN6zpaHUkCLorEWNx75MG0xhMwcFhvjqm2KURZEAGw@mail.gmail.com
---
doc/src/sgml/logical-replication.sgml | 3 +-
doc/src/sgml/monitoring.sgml | 36 ++++++++----
src/backend/catalog/system_views.sql | 1 +
.../replication/logical/applyparallelworker.c | 6 +-
src/backend/replication/logical/launcher.c | 64 ++++++++++++++++------
src/backend/utils/adt/pgstatfuncs.c | 11 ++++
src/include/catalog/pg_proc.dat | 6 +-
src/include/replication/logicallauncher.h | 2 +
src/include/replication/worker_internal.h | 4 +-
src/test/regress/expected/rules.out | 3 +-
10 files changed, 99 insertions(+), 37 deletions(-)
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 54f48be..f4b4e64 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1692,7 +1692,8 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
subscription. A disabled subscription or a crashed subscription will have
zero rows in this view. If the initial data synchronization of any
table is in progress, there will be additional workers for the tables
- being synchronized.
+ being synchronized. Moreover, if the streaming transaction is applied in
+ parallel, there may be additional parallel apply workers.
</para>
</sect1>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 358d2ff..e3a783a 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -743,9 +743,11 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<structfield>leader_pid</structfield> <type>integer</type>
</para>
<para>
- Process ID of the parallel group leader, if this process is a
- parallel query worker. <literal>NULL</literal> if this process is a
- parallel group leader or does not participate in parallel query.
+ Process ID of the parallel group leader if this process is a parallel
+ query worker, or process ID of the leader apply worker if this process
+ is a parallel apply worker. <literal>NULL</literal> indicates that this
+ process is a parallel group leader or leader apply worker, or does not
+ participate in any parallel operation.
</para></entry>
</row>
@@ -3208,11 +3210,22 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<row>
<entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>leader_pid</structfield> <type>integer</type>
+ </para>
+ <para>
+ Process ID of the leader apply worker if this process is a parallel
+ apply worker; NULL if this process is a leader apply worker or a
+ synchronization worker
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
<structfield>relid</structfield> <type>oid</type>
</para>
<para>
- OID of the relation that the worker is synchronizing; null for the
- main apply worker
+ OID of the relation that the worker is synchronizing; NULL for the
+ leader apply worker and parallel apply workers
</para></entry>
</row>
@@ -3222,7 +3235,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Last write-ahead log location received, the initial value of
- this field being 0
+ this field being 0; NULL for parallel apply workers
</para></entry>
</row>
@@ -3231,7 +3244,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_send_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Send time of last message received from origin WAL sender
+ Send time of last message received from origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3240,7 +3254,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_receipt_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Receipt time of last message received from origin WAL sender
+ Receipt time of last message received from origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3249,7 +3264,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>latest_end_lsn</structfield> <type>pg_lsn</type>
</para>
<para>
- Last write-ahead log location reported to origin WAL sender
+ Last write-ahead log location reported to origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3259,7 +3275,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Time of last write-ahead log location reported to origin WAL
- sender
+ sender; NULL for parallel apply workers
</para></entry>
</row>
</tbody>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index d2a8c82..8608e3f 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -948,6 +948,7 @@ CREATE VIEW pg_stat_subscription AS
su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3dfcff2..3579e70 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -849,7 +849,7 @@ LogicalParallelApplyLoop(shm_mq_handle *mqh)
static void
pa_shutdown(int code, Datum arg)
{
- SendProcSignal(MyLogicalRepWorker->apply_leader_pid,
+ SendProcSignal(MyLogicalRepWorker->leader_pid,
PROCSIG_PARALLEL_APPLY_MESSAGE,
InvalidBackendId);
@@ -932,7 +932,7 @@ ParallelApplyWorkerMain(Datum main_arg)
error_mqh = shm_mq_attach(mq, seg, NULL);
pq_redirect_to_shm_mq(seg, error_mqh);
- pq_set_parallel_leader(MyLogicalRepWorker->apply_leader_pid,
+ pq_set_parallel_leader(MyLogicalRepWorker->leader_pid,
InvalidBackendId);
MyLogicalRepWorker->last_send_time = MyLogicalRepWorker->last_recv_time =
@@ -950,7 +950,7 @@ ParallelApplyWorkerMain(Datum main_arg)
* The parallel apply worker doesn't need to monopolize this replication
* origin which was already acquired by its leader process.
*/
- replorigin_session_setup(originid, MyLogicalRepWorker->apply_leader_pid);
+ replorigin_session_setup(originid, MyLogicalRepWorker->leader_pid);
replorigin_session_origin = originid;
CommitTransactionCommand();
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index afb7acd..ff97ae4 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -410,7 +410,7 @@ retry:
worker->relstate = SUBREL_STATE_UNKNOWN;
worker->relstate_lsn = InvalidXLogRecPtr;
worker->stream_fileset = NULL;
- worker->apply_leader_pid = is_parallel_apply_worker ? MyProcPid : InvalidPid;
+ worker->leader_pid = is_parallel_apply_worker ? MyProcPid : InvalidPid;
worker->parallel_apply = is_parallel_apply_worker;
worker->last_lsn = InvalidXLogRecPtr;
TIMESTAMP_NOBEGIN(worker->last_send_time);
@@ -732,7 +732,7 @@ logicalrep_worker_cleanup(LogicalRepWorker *worker)
worker->userid = InvalidOid;
worker->subid = InvalidOid;
worker->relid = InvalidOid;
- worker->apply_leader_pid = InvalidPid;
+ worker->leader_pid = InvalidPid;
worker->parallel_apply = false;
}
@@ -1067,12 +1067,40 @@ IsLogicalLauncher(void)
}
/*
+ * Return the pid of the leader apply worker if the given pid is the pid of a
+ * parallel apply worker, otherwise return InvalidPid.
+ */
+pid_t
+GetLeaderApplyWorkerPid(pid_t pid)
+{
+ int leader_pid = InvalidPid;
+ int i;
+
+ LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
+
+ for (i = 0; i < max_logical_replication_workers; i++)
+ {
+ LogicalRepWorker *w = &LogicalRepCtx->workers[i];
+
+ if (isParallelApplyWorker(w) && w->proc && pid == w->proc->pid)
+ {
+ leader_pid = w->leader_pid;
+ break;
+ }
+ }
+
+ LWLockRelease(LogicalRepWorkerLock);
+
+ return leader_pid;
+}
+
+/*
* Returns state of the subscriptions.
*/
Datum
pg_stat_get_subscription(PG_FUNCTION_ARGS)
{
-#define PG_STAT_GET_SUBSCRIPTION_COLS 8
+#define PG_STAT_GET_SUBSCRIPTION_COLS 9
Oid subid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
int i;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
@@ -1098,10 +1126,6 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
if (OidIsValid(subid) && worker.subid != subid)
continue;
- /* Skip if this is a parallel apply worker */
- if (isParallelApplyWorker(&worker))
- continue;
-
worker_pid = worker.proc->pid;
values[0] = ObjectIdGetDatum(worker.subid);
@@ -1110,26 +1134,32 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
else
nulls[1] = true;
values[2] = Int32GetDatum(worker_pid);
- if (XLogRecPtrIsInvalid(worker.last_lsn))
+
+ if (isParallelApplyWorker(&worker))
+ values[3] = Int32GetDatum(worker.leader_pid);
+ else
nulls[3] = true;
+
+ if (XLogRecPtrIsInvalid(worker.last_lsn))
+ nulls[4] = true;
else
- values[3] = LSNGetDatum(worker.last_lsn);
+ values[4] = LSNGetDatum(worker.last_lsn);
if (worker.last_send_time == 0)
- nulls[4] = true;
+ nulls[5] = true;
else
- values[4] = TimestampTzGetDatum(worker.last_send_time);
+ values[5] = TimestampTzGetDatum(worker.last_send_time);
if (worker.last_recv_time == 0)
- nulls[5] = true;
+ nulls[6] = true;
else
- values[5] = TimestampTzGetDatum(worker.last_recv_time);
+ values[6] = TimestampTzGetDatum(worker.last_recv_time);
if (XLogRecPtrIsInvalid(worker.reply_lsn))
- nulls[6] = true;
+ nulls[7] = true;
else
- values[6] = LSNGetDatum(worker.reply_lsn);
+ values[7] = LSNGetDatum(worker.reply_lsn);
if (worker.reply_time == 0)
- nulls[7] = true;
+ nulls[8] = true;
else
- values[7] = TimestampTzGetDatum(worker.reply_time);
+ values[8] = TimestampTzGetDatum(worker.reply_time);
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
values, nulls);
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 58bd136..415e711 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -25,6 +25,7 @@
#include "pgstat.h"
#include "postmaster/bgworker_internals.h"
#include "postmaster/postmaster.h"
+#include "replication/logicallauncher.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/acl.h"
@@ -434,6 +435,16 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
values[28] = Int32GetDatum(leader->pid);
nulls[28] = false;
}
+ else
+ {
+ int leader_pid = GetLeaderApplyWorkerPid(beentry->st_procpid);
+
+ if (leader_pid != InvalidPid)
+ {
+ values[28] = Int32GetDatum(leader_pid);
+ nulls[28] = false;
+ }
+ }
}
if (wait_event_type)
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3810de7..86eb8e8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5430,9 +5430,9 @@
proname => 'pg_stat_get_subscription', prorows => '10', proisstrict => 'f',
proretset => 't', provolatile => 's', proparallel => 'r',
prorettype => 'record', proargtypes => 'oid',
- proallargtypes => '{oid,oid,oid,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
- proargmodes => '{i,o,o,o,o,o,o,o,o}',
- proargnames => '{subid,subid,relid,pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
+ proallargtypes => '{oid,oid,oid,int4,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{subid,subid,relid,pid,leader_pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
prosrc => 'pg_stat_get_subscription' },
{ oid => '2026', descr => 'statistics: current backend PID',
proname => 'pg_backend_pid', provolatile => 's', proparallel => 'r',
diff --git a/src/include/replication/logicallauncher.h b/src/include/replication/logicallauncher.h
index c85593a..360e987 100644
--- a/src/include/replication/logicallauncher.h
+++ b/src/include/replication/logicallauncher.h
@@ -27,4 +27,6 @@ extern void AtEOXact_ApplyLauncher(bool isCommit);
extern bool IsLogicalLauncher(void);
+extern pid_t GetLeaderApplyWorkerPid(pid_t pid);
+
#endif /* LOGICALLAUNCHER_H */
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index db891ee..dc87a4e 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -71,7 +71,7 @@ typedef struct LogicalRepWorker
* PID of leader apply worker if this slot is used for a parallel apply
* worker, InvalidPid otherwise.
*/
- pid_t apply_leader_pid;
+ pid_t leader_pid;
/* Indicates whether apply can be performed in parallel. */
bool parallel_apply;
@@ -303,7 +303,7 @@ extern void pa_decr_and_wait_stream_block(void);
extern void pa_xact_finish(ParallelApplyWorkerInfo *winfo,
XLogRecPtr remote_lsn);
-#define isParallelApplyWorker(worker) ((worker)->apply_leader_pid != InvalidPid)
+#define isParallelApplyWorker(worker) ((worker)->leader_pid != InvalidPid)
static inline bool
am_tablesync_worker(void)
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index a969ae6..05eec2a 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2094,6 +2094,7 @@ pg_stat_ssl| SELECT s.pid,
pg_stat_subscription| SELECT su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
@@ -2101,7 +2102,7 @@ pg_stat_subscription| SELECT su.oid AS subid,
st.latest_end_lsn,
st.latest_end_time
FROM (pg_subscription su
- LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
+ LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, leader_pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
pg_stat_subscription_stats| SELECT ss.subid,
s.subname,
ss.apply_error_count,
--
1.8.3.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-16 04:54 ` Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Peter Smith @ 2023-01-16 04:54 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
Here are some review comments for v81-0001.
======
Commit Message
1.
Additionally, update the leader_pid column in pg_stat_activity as well to
display the PID of the leader apply worker for parallel apply workers.
~
Probably it should not say both "Additionally" and "as well" in the
same sentence.
======
src/backend/replication/logical/launcher.c
2.
/*
+ * Return the pid of the leader apply worker if the given pid is the pid of a
+ * parallel apply worker, otherwise return InvalidPid.
+ */
+pid_t
+GetLeaderApplyWorkerPid(pid_t pid)
+{
+ int leader_pid = InvalidPid;
+ int i;
+
+ LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
+
+ for (i = 0; i < max_logical_replication_workers; i++)
+ {
+ LogicalRepWorker *w = &LogicalRepCtx->workers[i];
+
+ if (isParallelApplyWorker(w) && w->proc && pid == w->proc->pid)
+ {
+ leader_pid = w->leader_pid;
+ break;
+ }
+ }
+
+ LWLockRelease(LogicalRepWorkerLock);
+
+ return leader_pid;
+}
2a.
IIUC the IsParallelApplyWorker macro does nothing except check that
the leader_pid is not InvalidPid anyway, so AFAIK this algorithm does
not benefit from using this macro because we will want to return
InvalidPid anyway if the given pid matches.
So the inner condition can just say:
if (w->proc && w->proc->pid == pid)
{
leader_pid = w->leader_pid;
break;
}
~
2b.
A possible alternative comment.
BEFORE
Return the pid of the leader apply worker if the given pid is the pid
of a parallel apply worker, otherwise return InvalidPid.
AFTER
If the given pid has a leader apply worker then return the leader pid,
otherwise, return InvalidPid.
======
src/backend/utils/adt/pgstatfuncs.c
3.
@@ -434,6 +435,16 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
values[28] = Int32GetDatum(leader->pid);
nulls[28] = false;
}
+ else
+ {
+ int leader_pid = GetLeaderApplyWorkerPid(beentry->st_procpid);
+
+ if (leader_pid != InvalidPid)
+ {
+ values[28] = Int32GetDatum(leader_pid);
+ nulls[28] = false;
+ }
+
3a.
There is an existing comment preceding this if/else but it refers only
to leaders of parallel groups. Should that comment be updated to
mention the leader apply worker too?
~
3b.
It may be unrelated to this patch, but it seems strange to me that the
nulls[28]/values[28] assignments are done where they are. Every other
nulls/values assignment of this function here is pretty much in the
correct numerical order except this one, so IMO this code ought to be
relocated to later in this same function.
------
Kind Regards,
Peter Smith.
Fujitsu Australia.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-16 06:40 ` Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-01-16 06:40 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Mon, Jan 16, 2023 at 10:24 AM Peter Smith <[email protected]> wrote:
>
> 2.
>
> /*
> + * Return the pid of the leader apply worker if the given pid is the pid of a
> + * parallel apply worker, otherwise return InvalidPid.
> + */
> +pid_t
> +GetLeaderApplyWorkerPid(pid_t pid)
> +{
> + int leader_pid = InvalidPid;
> + int i;
> +
> + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
> +
> + for (i = 0; i < max_logical_replication_workers; i++)
> + {
> + LogicalRepWorker *w = &LogicalRepCtx->workers[i];
> +
> + if (isParallelApplyWorker(w) && w->proc && pid == w->proc->pid)
> + {
> + leader_pid = w->leader_pid;
> + break;
> + }
> + }
> +
> + LWLockRelease(LogicalRepWorkerLock);
> +
> + return leader_pid;
> +}
>
> 2a.
> IIUC the IsParallelApplyWorker macro does nothing except check that
> the leader_pid is not InvalidPid anyway, so AFAIK this algorithm does
> not benefit from using this macro because we will want to return
> InvalidPid anyway if the given pid matches.
>
> So the inner condition can just say:
>
> if (w->proc && w->proc->pid == pid)
> {
> leader_pid = w->leader_pid;
> break;
> }
>
Yeah, this should also work but I feel the current one is explicit and
more clear.
> ~
>
> 2b.
> A possible alternative comment.
>
> BEFORE
> Return the pid of the leader apply worker if the given pid is the pid
> of a parallel apply worker, otherwise return InvalidPid.
>
>
> AFTER
> If the given pid has a leader apply worker then return the leader pid,
> otherwise, return InvalidPid.
>
I don't think that is an improvement.
> ======
>
> src/backend/utils/adt/pgstatfuncs.c
>
> 3.
>
> @@ -434,6 +435,16 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
> values[28] = Int32GetDatum(leader->pid);
> nulls[28] = false;
> }
> + else
> + {
> + int leader_pid = GetLeaderApplyWorkerPid(beentry->st_procpid);
> +
> + if (leader_pid != InvalidPid)
> + {
> + values[28] = Int32GetDatum(leader_pid);
> + nulls[28] = false;
> + }
> +
>
> 3a.
> There is an existing comment preceding this if/else but it refers only
> to leaders of parallel groups. Should that comment be updated to
> mention the leader apply worker too?
>
Yeah, we can slightly adjust the comments. How about something like the below:
index 415e711729..7eb668634a 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -410,9 +410,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
/*
* If a PGPROC entry was retrieved, display
wait events and lock
- * group leader information if any. To avoid
extra overhead, no
- * extra lock is being held, so there is no guarantee of
- * consistency across multiple rows.
+ * group leader or apply leader information if
any. To avoid extra
+ * overhead, no extra lock is being held, so
there is no guarantee
+ * of consistency across multiple rows.
*/
if (proc != NULL)
{
@@ -428,7 +428,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
/*
* Show the leader only for active
parallel workers. This
* leaves the field as NULL for the
leader of a parallel
- * group.
+ * group or the leader of a parallel apply.
*/
if (leader && leader->pid !=
beentry->st_procpid)
> ~
>
> 3b.
> It may be unrelated to this patch, but it seems strange to me that the
> nulls[28]/values[28] assignments are done where they are. Every other
> nulls/values assignment of this function here is pretty much in the
> correct numerical order except this one, so IMO this code ought to be
> relocated to later in this same function.
>
This is not related to the current patch but I see there is merit in
the current coding as it is better to retrieve all the fields of proc
together.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-16 21:42 ` Peter Smith <[email protected]>
2023-01-17 02:21 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Peter Smith @ 2023-01-16 21:42 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Mon, Jan 16, 2023 at 5:41 PM Amit Kapila <[email protected]> wrote:
>
> On Mon, Jan 16, 2023 at 10:24 AM Peter Smith <[email protected]> wrote:
> >
> > 2.
> >
> > /*
> > + * Return the pid of the leader apply worker if the given pid is the pid of a
> > + * parallel apply worker, otherwise return InvalidPid.
> > + */
> > +pid_t
> > +GetLeaderApplyWorkerPid(pid_t pid)
> > +{
> > + int leader_pid = InvalidPid;
> > + int i;
> > +
> > + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
> > +
> > + for (i = 0; i < max_logical_replication_workers; i++)
> > + {
> > + LogicalRepWorker *w = &LogicalRepCtx->workers[i];
> > +
> > + if (isParallelApplyWorker(w) && w->proc && pid == w->proc->pid)
> > + {
> > + leader_pid = w->leader_pid;
> > + break;
> > + }
> > + }
> > +
> > + LWLockRelease(LogicalRepWorkerLock);
> > +
> > + return leader_pid;
> > +}
> >
> > 2a.
> > IIUC the IsParallelApplyWorker macro does nothing except check that
> > the leader_pid is not InvalidPid anyway, so AFAIK this algorithm does
> > not benefit from using this macro because we will want to return
> > InvalidPid anyway if the given pid matches.
> >
> > So the inner condition can just say:
> >
> > if (w->proc && w->proc->pid == pid)
> > {
> > leader_pid = w->leader_pid;
> > break;
> > }
> >
>
> Yeah, this should also work but I feel the current one is explicit and
> more clear.
OK.
But, I have one last comment about this function -- I saw there are
already other functions that iterate max_logical_replication_workers
like this looking for things:
- logicalrep_worker_find
- logicalrep_workers_find
- logicalrep_worker_launch
- logicalrep_sync_worker_count
So I felt this new function (currently called GetLeaderApplyWorkerPid)
ought to be named similarly to those ones. e.g. call it something like
"logicalrep_worker_find_pa_leader_pid".
>
> > ~
> >
> > 2b.
> > A possible alternative comment.
> >
> > BEFORE
> > Return the pid of the leader apply worker if the given pid is the pid
> > of a parallel apply worker, otherwise return InvalidPid.
> >
> >
> > AFTER
> > If the given pid has a leader apply worker then return the leader pid,
> > otherwise, return InvalidPid.
> >
>
> I don't think that is an improvement.
>
> > ======
> >
> > src/backend/utils/adt/pgstatfuncs.c
> >
> > 3.
> >
> > @@ -434,6 +435,16 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
> > values[28] = Int32GetDatum(leader->pid);
> > nulls[28] = false;
> > }
> > + else
> > + {
> > + int leader_pid = GetLeaderApplyWorkerPid(beentry->st_procpid);
> > +
> > + if (leader_pid != InvalidPid)
> > + {
> > + values[28] = Int32GetDatum(leader_pid);
> > + nulls[28] = false;
> > + }
> > +
> >
> > 3a.
> > There is an existing comment preceding this if/else but it refers only
> > to leaders of parallel groups. Should that comment be updated to
> > mention the leader apply worker too?
> >
>
> Yeah, we can slightly adjust the comments. How about something like the below:
> index 415e711729..7eb668634a 100644
> --- a/src/backend/utils/adt/pgstatfuncs.c
> +++ b/src/backend/utils/adt/pgstatfuncs.c
> @@ -410,9 +410,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
>
> /*
> * If a PGPROC entry was retrieved, display
> wait events and lock
> - * group leader information if any. To avoid
> extra overhead, no
> - * extra lock is being held, so there is no guarantee of
> - * consistency across multiple rows.
> + * group leader or apply leader information if
> any. To avoid extra
> + * overhead, no extra lock is being held, so
> there is no guarantee
> + * of consistency across multiple rows.
> */
> if (proc != NULL)
> {
> @@ -428,7 +428,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
> /*
> * Show the leader only for active
> parallel workers. This
> * leaves the field as NULL for the
> leader of a parallel
> - * group.
> + * group or the leader of a parallel apply.
> */
> if (leader && leader->pid !=
> beentry->st_procpid)
>
The updated comment LGTM.
------
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-17 02:21 ` [email protected] <[email protected]>
2023-01-17 03:32 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: [email protected] @ 2023-01-17 02:21 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Amit Kapila <[email protected]>
On Tuesday, January 17, 2023 5:43 AM Peter Smith <[email protected]> wrote:
>
> On Mon, Jan 16, 2023 at 5:41 PM Amit Kapila <[email protected]>
> wrote:
> >
> > On Mon, Jan 16, 2023 at 10:24 AM Peter Smith <[email protected]>
> wrote:
> > >
> > > 2.
> > >
> > > /*
> > > + * Return the pid of the leader apply worker if the given pid is
> > > +the pid of a
> > > + * parallel apply worker, otherwise return InvalidPid.
> > > + */
> > > +pid_t
> > > +GetLeaderApplyWorkerPid(pid_t pid)
> > > +{
> > > + int leader_pid = InvalidPid;
> > > + int i;
> > > +
> > > + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
> > > +
> > > + for (i = 0; i < max_logical_replication_workers; i++) {
> > > + LogicalRepWorker *w = &LogicalRepCtx->workers[i];
> > > +
> > > + if (isParallelApplyWorker(w) && w->proc && pid == w->proc->pid) {
> > > + leader_pid = w->leader_pid; break; } }
> > > +
> > > + LWLockRelease(LogicalRepWorkerLock);
> > > +
> > > + return leader_pid;
> > > +}
> > >
> > > 2a.
> > > IIUC the IsParallelApplyWorker macro does nothing except check that
> > > the leader_pid is not InvalidPid anyway, so AFAIK this algorithm
> > > does not benefit from using this macro because we will want to
> > > return InvalidPid anyway if the given pid matches.
> > >
> > > So the inner condition can just say:
> > >
> > > if (w->proc && w->proc->pid == pid)
> > > {
> > > leader_pid = w->leader_pid;
> > > break;
> > > }
> > >
> >
> > Yeah, this should also work but I feel the current one is explicit and
> > more clear.
>
> OK.
>
> But, I have one last comment about this function -- I saw there are already
> other functions that iterate max_logical_replication_workers like this looking
> for things:
> - logicalrep_worker_find
> - logicalrep_workers_find
> - logicalrep_worker_launch
> - logicalrep_sync_worker_count
>
> So I felt this new function (currently called GetLeaderApplyWorkerPid) ought
> to be named similarly to those ones. e.g. call it something like
> "logicalrep_worker_find_pa_leader_pid".
>
I am not sure we can use the name, because currently all the API name in launcher that
used by other module(not related to subscription) are like
AxxBxx style(see the functions in logicallauncher.h).
logicalrep_worker_xxx style functions are currently only declared in
worker_internal.h.
Best regards,
Hou zj
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 02:21 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-17 03:32 ` Peter Smith <[email protected]>
2023-01-17 03:37 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Peter Smith @ 2023-01-17 03:32 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Amit Kapila <[email protected]>
On Tue, Jan 17, 2023 at 1:21 PM [email protected]
<[email protected]> wrote:
>
> On Tuesday, January 17, 2023 5:43 AM Peter Smith <[email protected]> wrote:
> >
> > On Mon, Jan 16, 2023 at 5:41 PM Amit Kapila <[email protected]>
> > wrote:
> > >
> > > On Mon, Jan 16, 2023 at 10:24 AM Peter Smith <[email protected]>
> > wrote:
> > > >
> > > > 2.
> > > >
> > > > /*
> > > > + * Return the pid of the leader apply worker if the given pid is
> > > > +the pid of a
> > > > + * parallel apply worker, otherwise return InvalidPid.
> > > > + */
> > > > +pid_t
> > > > +GetLeaderApplyWorkerPid(pid_t pid)
> > > > +{
> > > > + int leader_pid = InvalidPid;
> > > > + int i;
> > > > +
> > > > + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
> > > > +
> > > > + for (i = 0; i < max_logical_replication_workers; i++) {
> > > > + LogicalRepWorker *w = &LogicalRepCtx->workers[i];
> > > > +
> > > > + if (isParallelApplyWorker(w) && w->proc && pid == w->proc->pid) {
> > > > + leader_pid = w->leader_pid; break; } }
> > > > +
> > > > + LWLockRelease(LogicalRepWorkerLock);
> > > > +
> > > > + return leader_pid;
> > > > +}
> > > >
> > > > 2a.
> > > > IIUC the IsParallelApplyWorker macro does nothing except check that
> > > > the leader_pid is not InvalidPid anyway, so AFAIK this algorithm
> > > > does not benefit from using this macro because we will want to
> > > > return InvalidPid anyway if the given pid matches.
> > > >
> > > > So the inner condition can just say:
> > > >
> > > > if (w->proc && w->proc->pid == pid)
> > > > {
> > > > leader_pid = w->leader_pid;
> > > > break;
> > > > }
> > > >
> > >
> > > Yeah, this should also work but I feel the current one is explicit and
> > > more clear.
> >
> > OK.
> >
> > But, I have one last comment about this function -- I saw there are already
> > other functions that iterate max_logical_replication_workers like this looking
> > for things:
> > - logicalrep_worker_find
> > - logicalrep_workers_find
> > - logicalrep_worker_launch
> > - logicalrep_sync_worker_count
> >
> > So I felt this new function (currently called GetLeaderApplyWorkerPid) ought
> > to be named similarly to those ones. e.g. call it something like
> > "logicalrep_worker_find_pa_leader_pid".
> >
>
> I am not sure we can use the name, because currently all the API name in launcher that
> used by other module(not related to subscription) are like
> AxxBxx style(see the functions in logicallauncher.h).
> logicalrep_worker_xxx style functions are currently only declared in
> worker_internal.h.
>
OK. I didn't know there was another header convention that you were
following. In that case, it is fine to leave the name as-is.
------
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 02:21 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 03:32 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-17 03:37 ` [email protected] <[email protected]>
2023-01-17 03:48 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 06:46 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 2 replies; 105+ messages in thread
From: [email protected] @ 2023-01-17 03:37 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Amit Kapila <[email protected]>
On Tuesday, January 17, 2023 11:32 AM Peter Smith <[email protected]> wrote:
>
> On Tue, Jan 17, 2023 at 1:21 PM [email protected]
> <[email protected]> wrote:
> >
> > On Tuesday, January 17, 2023 5:43 AM Peter Smith
> <[email protected]> wrote:
> > >
> > > On Mon, Jan 16, 2023 at 5:41 PM Amit Kapila
> > > <[email protected]>
> > > wrote:
> > > >
> > > > On Mon, Jan 16, 2023 at 10:24 AM Peter Smith
> > > > <[email protected]>
> > > wrote:
> > > > >
> > > > > 2.
> > > > >
> > > > > /*
> > > > > + * Return the pid of the leader apply worker if the given pid
> > > > > +is the pid of a
> > > > > + * parallel apply worker, otherwise return InvalidPid.
> > > > > + */
> > > > > +pid_t
> > > > > +GetLeaderApplyWorkerPid(pid_t pid) { int leader_pid =
> > > > > +InvalidPid; int i;
> > > > > +
> > > > > + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
> > > > > +
> > > > > + for (i = 0; i < max_logical_replication_workers; i++) {
> > > > > + LogicalRepWorker *w = &LogicalRepCtx->workers[i];
> > > > > +
> > > > > + if (isParallelApplyWorker(w) && w->proc && pid ==
> > > > > + w->proc->pid) { leader_pid = w->leader_pid; break; } }
> > > > > +
> > > > > + LWLockRelease(LogicalRepWorkerLock);
> > > > > +
> > > > > + return leader_pid;
> > > > > +}
> > > > >
> > > > > 2a.
> > > > > IIUC the IsParallelApplyWorker macro does nothing except check
> > > > > that the leader_pid is not InvalidPid anyway, so AFAIK this
> > > > > algorithm does not benefit from using this macro because we will
> > > > > want to return InvalidPid anyway if the given pid matches.
> > > > >
> > > > > So the inner condition can just say:
> > > > >
> > > > > if (w->proc && w->proc->pid == pid) { leader_pid =
> > > > > w->leader_pid; break; }
> > > > >
> > > >
> > > > Yeah, this should also work but I feel the current one is explicit
> > > > and more clear.
> > >
> > > OK.
> > >
> > > But, I have one last comment about this function -- I saw there are
> > > already other functions that iterate max_logical_replication_workers
> > > like this looking for things:
> > > - logicalrep_worker_find
> > > - logicalrep_workers_find
> > > - logicalrep_worker_launch
> > > - logicalrep_sync_worker_count
> > >
> > > So I felt this new function (currently called
> > > GetLeaderApplyWorkerPid) ought to be named similarly to those ones.
> > > e.g. call it something like "logicalrep_worker_find_pa_leader_pid".
> > >
> >
> > I am not sure we can use the name, because currently all the API name
> > in launcher that used by other module(not related to subscription) are
> > like AxxBxx style(see the functions in logicallauncher.h).
> > logicalrep_worker_xxx style functions are currently only declared in
> > worker_internal.h.
> >
>
> OK. I didn't know there was another header convention that you were following.
> In that case, it is fine to leave the name as-is.
Thanks for confirming!
Attach the new version 0001 patch which addressed all other comments.
Best regards,
Hou zj
Attachments:
[application/octet-stream] v82-0001-Display-the-leader-apply-worker-s-PID-for-parall.patch (16.6K, ../../OS0PR01MB57169845E9A6DEF86A7D682D94C69@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v82-0001-Display-the-leader-apply-worker-s-PID-for-parall.patch)
download | inline diff:
From f26897ebe46dc0822df9a8b843f404ff2187684c Mon Sep 17 00:00:00 2001
From: "houzj.fnst" <[email protected]>
Date: Thu, 6 Oct 2022 14:42:24 +0800
Subject: [PATCH v82] Display the leader apply worker's PID for parallel apply
workers.
Add leader_pid to pg_stat_subscription. leader_pid is the process ID of
the leader apply worker if this process is a parallel apply worker. If
this field is NULL, it indicates that the process is a leader apply
worker or a synchronization worker. The new column makes it easier to
distinguish parallel apply workers from other kinds of workers and helps
to identify the leader for the parallel workers corresponding to a
particular subscription.
Additionally, update the leader_pid column in pg_stat_activity to
display the PID of the leader apply worker for parallel apply workers.
Author: Hou Zhijie
Reviewed-by: Peter Smith, Sawada Masahiko, Amit Kapila
Discussion: https://postgr.es/m/CAA4eK1+wyN6zpaHUkCLorEWNx75MG0xhMwcFhvjqm2KURZEAGw@mail.gmail.com
---
doc/src/sgml/logical-replication.sgml | 3 +-
doc/src/sgml/monitoring.sgml | 36 ++++++++---
src/backend/catalog/system_views.sql | 1 +
.../replication/logical/applyparallelworker.c | 6 +-
src/backend/replication/logical/launcher.c | 64 ++++++++++++++-----
src/backend/utils/adt/pgstatfuncs.c | 21 ++++--
src/include/catalog/pg_proc.dat | 6 +-
src/include/replication/logicallauncher.h | 2 +
src/include/replication/worker_internal.h | 4 +-
src/test/regress/expected/rules.out | 3 +-
10 files changed, 104 insertions(+), 42 deletions(-)
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 54f48be87f..f4b4e641be 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1692,7 +1692,8 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
subscription. A disabled subscription or a crashed subscription will have
zero rows in this view. If the initial data synchronization of any
table is in progress, there will be additional workers for the tables
- being synchronized.
+ being synchronized. Moreover, if the streaming transaction is applied in
+ parallel, there may be additional parallel apply workers.
</para>
</sect1>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 358d2ff90f..e3a783abd0 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -743,9 +743,11 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<structfield>leader_pid</structfield> <type>integer</type>
</para>
<para>
- Process ID of the parallel group leader, if this process is a
- parallel query worker. <literal>NULL</literal> if this process is a
- parallel group leader or does not participate in parallel query.
+ Process ID of the parallel group leader if this process is a parallel
+ query worker, or process ID of the leader apply worker if this process
+ is a parallel apply worker. <literal>NULL</literal> indicates that this
+ process is a parallel group leader or leader apply worker, or does not
+ participate in any parallel operation.
</para></entry>
</row>
@@ -3206,13 +3208,24 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para></entry>
</row>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>leader_pid</structfield> <type>integer</type>
+ </para>
+ <para>
+ Process ID of the leader apply worker if this process is a parallel
+ apply worker; NULL if this process is a leader apply worker or a
+ synchronization worker
+ </para></entry>
+ </row>
+
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>relid</structfield> <type>oid</type>
</para>
<para>
- OID of the relation that the worker is synchronizing; null for the
- main apply worker
+ OID of the relation that the worker is synchronizing; NULL for the
+ leader apply worker and parallel apply workers
</para></entry>
</row>
@@ -3222,7 +3235,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Last write-ahead log location received, the initial value of
- this field being 0
+ this field being 0; NULL for parallel apply workers
</para></entry>
</row>
@@ -3231,7 +3244,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_send_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Send time of last message received from origin WAL sender
+ Send time of last message received from origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3240,7 +3254,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_receipt_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Receipt time of last message received from origin WAL sender
+ Receipt time of last message received from origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3249,7 +3264,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>latest_end_lsn</structfield> <type>pg_lsn</type>
</para>
<para>
- Last write-ahead log location reported to origin WAL sender
+ Last write-ahead log location reported to origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3259,7 +3275,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Time of last write-ahead log location reported to origin WAL
- sender
+ sender; NULL for parallel apply workers
</para></entry>
</row>
</tbody>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index d2a8c82900..8608e3fa5b 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -948,6 +948,7 @@ CREATE VIEW pg_stat_subscription AS
su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3dfcff2798..3579e704fe 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -849,7 +849,7 @@ LogicalParallelApplyLoop(shm_mq_handle *mqh)
static void
pa_shutdown(int code, Datum arg)
{
- SendProcSignal(MyLogicalRepWorker->apply_leader_pid,
+ SendProcSignal(MyLogicalRepWorker->leader_pid,
PROCSIG_PARALLEL_APPLY_MESSAGE,
InvalidBackendId);
@@ -932,7 +932,7 @@ ParallelApplyWorkerMain(Datum main_arg)
error_mqh = shm_mq_attach(mq, seg, NULL);
pq_redirect_to_shm_mq(seg, error_mqh);
- pq_set_parallel_leader(MyLogicalRepWorker->apply_leader_pid,
+ pq_set_parallel_leader(MyLogicalRepWorker->leader_pid,
InvalidBackendId);
MyLogicalRepWorker->last_send_time = MyLogicalRepWorker->last_recv_time =
@@ -950,7 +950,7 @@ ParallelApplyWorkerMain(Datum main_arg)
* The parallel apply worker doesn't need to monopolize this replication
* origin which was already acquired by its leader process.
*/
- replorigin_session_setup(originid, MyLogicalRepWorker->apply_leader_pid);
+ replorigin_session_setup(originid, MyLogicalRepWorker->leader_pid);
replorigin_session_origin = originid;
CommitTransactionCommand();
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index afb7acddaa..ff97ae4ffb 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -410,7 +410,7 @@ retry:
worker->relstate = SUBREL_STATE_UNKNOWN;
worker->relstate_lsn = InvalidXLogRecPtr;
worker->stream_fileset = NULL;
- worker->apply_leader_pid = is_parallel_apply_worker ? MyProcPid : InvalidPid;
+ worker->leader_pid = is_parallel_apply_worker ? MyProcPid : InvalidPid;
worker->parallel_apply = is_parallel_apply_worker;
worker->last_lsn = InvalidXLogRecPtr;
TIMESTAMP_NOBEGIN(worker->last_send_time);
@@ -732,7 +732,7 @@ logicalrep_worker_cleanup(LogicalRepWorker *worker)
worker->userid = InvalidOid;
worker->subid = InvalidOid;
worker->relid = InvalidOid;
- worker->apply_leader_pid = InvalidPid;
+ worker->leader_pid = InvalidPid;
worker->parallel_apply = false;
}
@@ -1066,13 +1066,41 @@ IsLogicalLauncher(void)
return LogicalRepCtx->launcher_pid == MyProcPid;
}
+/*
+ * Return the pid of the leader apply worker if the given pid is the pid of a
+ * parallel apply worker, otherwise, return InvalidPid.
+ */
+pid_t
+GetLeaderApplyWorkerPid(pid_t pid)
+{
+ int leader_pid = InvalidPid;
+ int i;
+
+ LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
+
+ for (i = 0; i < max_logical_replication_workers; i++)
+ {
+ LogicalRepWorker *w = &LogicalRepCtx->workers[i];
+
+ if (isParallelApplyWorker(w) && w->proc && pid == w->proc->pid)
+ {
+ leader_pid = w->leader_pid;
+ break;
+ }
+ }
+
+ LWLockRelease(LogicalRepWorkerLock);
+
+ return leader_pid;
+}
+
/*
* Returns state of the subscriptions.
*/
Datum
pg_stat_get_subscription(PG_FUNCTION_ARGS)
{
-#define PG_STAT_GET_SUBSCRIPTION_COLS 8
+#define PG_STAT_GET_SUBSCRIPTION_COLS 9
Oid subid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
int i;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
@@ -1098,10 +1126,6 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
if (OidIsValid(subid) && worker.subid != subid)
continue;
- /* Skip if this is a parallel apply worker */
- if (isParallelApplyWorker(&worker))
- continue;
-
worker_pid = worker.proc->pid;
values[0] = ObjectIdGetDatum(worker.subid);
@@ -1110,26 +1134,32 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
else
nulls[1] = true;
values[2] = Int32GetDatum(worker_pid);
- if (XLogRecPtrIsInvalid(worker.last_lsn))
+
+ if (isParallelApplyWorker(&worker))
+ values[3] = Int32GetDatum(worker.leader_pid);
+ else
nulls[3] = true;
+
+ if (XLogRecPtrIsInvalid(worker.last_lsn))
+ nulls[4] = true;
else
- values[3] = LSNGetDatum(worker.last_lsn);
+ values[4] = LSNGetDatum(worker.last_lsn);
if (worker.last_send_time == 0)
- nulls[4] = true;
+ nulls[5] = true;
else
- values[4] = TimestampTzGetDatum(worker.last_send_time);
+ values[5] = TimestampTzGetDatum(worker.last_send_time);
if (worker.last_recv_time == 0)
- nulls[5] = true;
+ nulls[6] = true;
else
- values[5] = TimestampTzGetDatum(worker.last_recv_time);
+ values[6] = TimestampTzGetDatum(worker.last_recv_time);
if (XLogRecPtrIsInvalid(worker.reply_lsn))
- nulls[6] = true;
+ nulls[7] = true;
else
- values[6] = LSNGetDatum(worker.reply_lsn);
+ values[7] = LSNGetDatum(worker.reply_lsn);
if (worker.reply_time == 0)
- nulls[7] = true;
+ nulls[8] = true;
else
- values[7] = TimestampTzGetDatum(worker.reply_time);
+ values[8] = TimestampTzGetDatum(worker.reply_time);
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
values, nulls);
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 58bd1360b9..a3bf95ff0f 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -25,6 +25,7 @@
#include "pgstat.h"
#include "postmaster/bgworker_internals.h"
#include "postmaster/postmaster.h"
+#include "replication/logicallauncher.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/acl.h"
@@ -409,9 +410,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
/*
* If a PGPROC entry was retrieved, display wait events and lock
- * group leader information if any. To avoid extra overhead, no
- * extra lock is being held, so there is no guarantee of
- * consistency across multiple rows.
+ * group leader or apply leader information if any. To avoid
+ * extra overhead, no extra lock is being held, so there is no
+ * guarantee of consistency across multiple rows.
*/
if (proc != NULL)
{
@@ -426,14 +427,24 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
/*
* Show the leader only for active parallel workers. This
- * leaves the field as NULL for the leader of a parallel
- * group.
+ * leaves the field as NULL for the leader of a parallel group
+ * or the leader of parallel apply workers.
*/
if (leader && leader->pid != beentry->st_procpid)
{
values[28] = Int32GetDatum(leader->pid);
nulls[28] = false;
}
+ else
+ {
+ int leader_pid = GetLeaderApplyWorkerPid(beentry->st_procpid);
+
+ if (leader_pid != InvalidPid)
+ {
+ values[28] = Int32GetDatum(leader_pid);
+ nulls[28] = false;
+ }
+ }
}
if (wait_event_type)
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3810de7b22..86eb8e8c58 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5430,9 +5430,9 @@
proname => 'pg_stat_get_subscription', prorows => '10', proisstrict => 'f',
proretset => 't', provolatile => 's', proparallel => 'r',
prorettype => 'record', proargtypes => 'oid',
- proallargtypes => '{oid,oid,oid,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
- proargmodes => '{i,o,o,o,o,o,o,o,o}',
- proargnames => '{subid,subid,relid,pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
+ proallargtypes => '{oid,oid,oid,int4,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{subid,subid,relid,pid,leader_pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
prosrc => 'pg_stat_get_subscription' },
{ oid => '2026', descr => 'statistics: current backend PID',
proname => 'pg_backend_pid', provolatile => 's', proparallel => 'r',
diff --git a/src/include/replication/logicallauncher.h b/src/include/replication/logicallauncher.h
index c85593ad11..360e98702a 100644
--- a/src/include/replication/logicallauncher.h
+++ b/src/include/replication/logicallauncher.h
@@ -27,4 +27,6 @@ extern void AtEOXact_ApplyLauncher(bool isCommit);
extern bool IsLogicalLauncher(void);
+extern pid_t GetLeaderApplyWorkerPid(pid_t pid);
+
#endif /* LOGICALLAUNCHER_H */
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index db891eea8a..dc87a4edd1 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -71,7 +71,7 @@ typedef struct LogicalRepWorker
* PID of leader apply worker if this slot is used for a parallel apply
* worker, InvalidPid otherwise.
*/
- pid_t apply_leader_pid;
+ pid_t leader_pid;
/* Indicates whether apply can be performed in parallel. */
bool parallel_apply;
@@ -303,7 +303,7 @@ extern void pa_decr_and_wait_stream_block(void);
extern void pa_xact_finish(ParallelApplyWorkerInfo *winfo,
XLogRecPtr remote_lsn);
-#define isParallelApplyWorker(worker) ((worker)->apply_leader_pid != InvalidPid)
+#define isParallelApplyWorker(worker) ((worker)->leader_pid != InvalidPid)
static inline bool
am_tablesync_worker(void)
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index a969ae63eb..05eec2adfd 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2094,6 +2094,7 @@ pg_stat_ssl| SELECT s.pid,
pg_stat_subscription| SELECT su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
@@ -2101,7 +2102,7 @@ pg_stat_subscription| SELECT su.oid AS subid,
st.latest_end_lsn,
st.latest_end_time
FROM (pg_subscription su
- LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
+ LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, leader_pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
pg_stat_subscription_stats| SELECT ss.subid,
s.subname,
ss.apply_error_count,
--
2.31.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 02:21 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 03:32 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 03:37 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-17 03:48 ` Peter Smith <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: Peter Smith @ 2023-01-17 03:48 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Amit Kapila <[email protected]>
On Tue, Jan 17, 2023 at 2:37 PM [email protected]
<[email protected]> wrote:
>
> On Tuesday, January 17, 2023 11:32 AM Peter Smith <[email protected]> wrote:
> >
> > On Tue, Jan 17, 2023 at 1:21 PM [email protected]
> > <[email protected]> wrote:
> > >
> > > On Tuesday, January 17, 2023 5:43 AM Peter Smith
> > <[email protected]> wrote:
> > > >
> > > > On Mon, Jan 16, 2023 at 5:41 PM Amit Kapila
> > > > <[email protected]>
> > > > wrote:
> > > > >
> > > > > On Mon, Jan 16, 2023 at 10:24 AM Peter Smith
> > > > > <[email protected]>
> > > > wrote:
> > > > > >
> > > > > > 2.
> > > > > >
> > > > > > /*
> > > > > > + * Return the pid of the leader apply worker if the given pid
> > > > > > +is the pid of a
> > > > > > + * parallel apply worker, otherwise return InvalidPid.
> > > > > > + */
> > > > > > +pid_t
> > > > > > +GetLeaderApplyWorkerPid(pid_t pid) { int leader_pid =
> > > > > > +InvalidPid; int i;
> > > > > > +
> > > > > > + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
> > > > > > +
> > > > > > + for (i = 0; i < max_logical_replication_workers; i++) {
> > > > > > + LogicalRepWorker *w = &LogicalRepCtx->workers[i];
> > > > > > +
> > > > > > + if (isParallelApplyWorker(w) && w->proc && pid ==
> > > > > > + w->proc->pid) { leader_pid = w->leader_pid; break; } }
> > > > > > +
> > > > > > + LWLockRelease(LogicalRepWorkerLock);
> > > > > > +
> > > > > > + return leader_pid;
> > > > > > +}
> > > > > >
> > > > > > 2a.
> > > > > > IIUC the IsParallelApplyWorker macro does nothing except check
> > > > > > that the leader_pid is not InvalidPid anyway, so AFAIK this
> > > > > > algorithm does not benefit from using this macro because we will
> > > > > > want to return InvalidPid anyway if the given pid matches.
> > > > > >
> > > > > > So the inner condition can just say:
> > > > > >
> > > > > > if (w->proc && w->proc->pid == pid) { leader_pid =
> > > > > > w->leader_pid; break; }
> > > > > >
> > > > >
> > > > > Yeah, this should also work but I feel the current one is explicit
> > > > > and more clear.
> > > >
> > > > OK.
> > > >
> > > > But, I have one last comment about this function -- I saw there are
> > > > already other functions that iterate max_logical_replication_workers
> > > > like this looking for things:
> > > > - logicalrep_worker_find
> > > > - logicalrep_workers_find
> > > > - logicalrep_worker_launch
> > > > - logicalrep_sync_worker_count
> > > >
> > > > So I felt this new function (currently called
> > > > GetLeaderApplyWorkerPid) ought to be named similarly to those ones.
> > > > e.g. call it something like "logicalrep_worker_find_pa_leader_pid".
> > > >
> > >
> > > I am not sure we can use the name, because currently all the API name
> > > in launcher that used by other module(not related to subscription) are
> > > like AxxBxx style(see the functions in logicallauncher.h).
> > > logicalrep_worker_xxx style functions are currently only declared in
> > > worker_internal.h.
> > >
> >
> > OK. I didn't know there was another header convention that you were following.
> > In that case, it is fine to leave the name as-is.
>
> Thanks for confirming!
>
> Attach the new version 0001 patch which addressed all other comments.
>
OK. I checked the differences between patches v81-0001/v82-0001 and
found everything I was expecting to see.
I have no more review comments for v82-0001.
------
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 02:21 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 03:32 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 03:37 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-17 06:46 ` Masahiko Sawada <[email protected]>
2023-01-17 09:14 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
1 sibling, 1 reply; 105+ messages in thread
From: Masahiko Sawada @ 2023-01-17 06:46 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Peter Smith <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Amit Kapila <[email protected]>
On Tue, Jan 17, 2023 at 12:37 PM [email protected]
<[email protected]> wrote:
>
> On Tuesday, January 17, 2023 11:32 AM Peter Smith <[email protected]> wrote:
> >
> > On Tue, Jan 17, 2023 at 1:21 PM [email protected]
> > <[email protected]> wrote:
> > >
> > > On Tuesday, January 17, 2023 5:43 AM Peter Smith
> > <[email protected]> wrote:
> > > >
> > > > On Mon, Jan 16, 2023 at 5:41 PM Amit Kapila
> > > > <[email protected]>
> > > > wrote:
> > > > >
> > > > > On Mon, Jan 16, 2023 at 10:24 AM Peter Smith
> > > > > <[email protected]>
> > > > wrote:
> > > > > >
> > > > > > 2.
> > > > > >
> > > > > > /*
> > > > > > + * Return the pid of the leader apply worker if the given pid
> > > > > > +is the pid of a
> > > > > > + * parallel apply worker, otherwise return InvalidPid.
> > > > > > + */
> > > > > > +pid_t
> > > > > > +GetLeaderApplyWorkerPid(pid_t pid) { int leader_pid =
> > > > > > +InvalidPid; int i;
> > > > > > +
> > > > > > + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
> > > > > > +
> > > > > > + for (i = 0; i < max_logical_replication_workers; i++) {
> > > > > > + LogicalRepWorker *w = &LogicalRepCtx->workers[i];
> > > > > > +
> > > > > > + if (isParallelApplyWorker(w) && w->proc && pid ==
> > > > > > + w->proc->pid) { leader_pid = w->leader_pid; break; } }
> > > > > > +
> > > > > > + LWLockRelease(LogicalRepWorkerLock);
> > > > > > +
> > > > > > + return leader_pid;
> > > > > > +}
> > > > > >
> > > > > > 2a.
> > > > > > IIUC the IsParallelApplyWorker macro does nothing except check
> > > > > > that the leader_pid is not InvalidPid anyway, so AFAIK this
> > > > > > algorithm does not benefit from using this macro because we will
> > > > > > want to return InvalidPid anyway if the given pid matches.
> > > > > >
> > > > > > So the inner condition can just say:
> > > > > >
> > > > > > if (w->proc && w->proc->pid == pid) { leader_pid =
> > > > > > w->leader_pid; break; }
> > > > > >
> > > > >
> > > > > Yeah, this should also work but I feel the current one is explicit
> > > > > and more clear.
> > > >
> > > > OK.
> > > >
> > > > But, I have one last comment about this function -- I saw there are
> > > > already other functions that iterate max_logical_replication_workers
> > > > like this looking for things:
> > > > - logicalrep_worker_find
> > > > - logicalrep_workers_find
> > > > - logicalrep_worker_launch
> > > > - logicalrep_sync_worker_count
> > > >
> > > > So I felt this new function (currently called
> > > > GetLeaderApplyWorkerPid) ought to be named similarly to those ones.
> > > > e.g. call it something like "logicalrep_worker_find_pa_leader_pid".
> > > >
> > >
> > > I am not sure we can use the name, because currently all the API name
> > > in launcher that used by other module(not related to subscription) are
> > > like AxxBxx style(see the functions in logicallauncher.h).
> > > logicalrep_worker_xxx style functions are currently only declared in
> > > worker_internal.h.
> > >
> >
> > OK. I didn't know there was another header convention that you were following.
> > In that case, it is fine to leave the name as-is.
>
> Thanks for confirming!
>
> Attach the new version 0001 patch which addressed all other comments.
>
Thank you for updating the patch. Here is one comment:
@@ -426,14 +427,24 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
/*
* Show the leader only for active
parallel workers. This
- * leaves the field as NULL for the
leader of a parallel
- * group.
+ * leaves the field as NULL for the
leader of a parallel group
+ * or the leader of parallel apply workers.
*/
if (leader && leader->pid !=
beentry->st_procpid)
{
values[28] = Int32GetDatum(leader->pid);
nulls[28] = false;
}
+ else
+ {
+ int
leader_pid = GetLeaderApplyWorkerPid(beentry->st_procpid);
+
+ if (leader_pid != InvalidPid)
+ {
+ values[28] =
Int32GetDatum(leader_pid);
+ nulls[28] = false;
+ }
+ }
}
I'm slightly concerned that there could be overhead of executing
GetLeaderApplyWorkerPid () for every backend process except for
parallel query workers. The number of such backends could be large and
GetLeaderApplyWorkerPid() acquires the lwlock. For example, does it
make sense to check (st_backendType == B_BG_WORKER) before calling
GetLeaderApplyWorkerPid()? Or it might not be a problem since it's
LogicalRepWorkerLock which is not likely to be contended.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 02:21 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 03:32 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 03:37 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 06:46 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-01-17 09:14 ` [email protected] <[email protected]>
2023-01-17 14:37 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: [email protected] @ 2023-01-17 09:14 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: Peter Smith <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Amit Kapila <[email protected]>
On Tuesday, January 17, 2023 2:46 PM Masahiko Sawada <[email protected]> wrote:
>
> On Tue, Jan 17, 2023 at 12:37 PM [email protected]
> <[email protected]> wrote:
> > Attach the new version 0001 patch which addressed all other comments.
> >
>
> Thank you for updating the patch. Here is one comment:
>
> @@ -426,14 +427,24 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
>
> /*
> * Show the leader only for active parallel
> workers. This
> - * leaves the field as NULL for the
> leader of a parallel
> - * group.
> + * leaves the field as NULL for the
> leader of a parallel group
> + * or the leader of parallel apply workers.
> */
> if (leader && leader->pid !=
> beentry->st_procpid)
> {
> values[28] =
> Int32GetDatum(leader->pid);
> nulls[28] = false;
> }
> + else
> + {
> + int
> leader_pid = GetLeaderApplyWorkerPid(beentry->st_procpid);
> +
> + if (leader_pid != InvalidPid)
> + {
> + values[28] =
> Int32GetDatum(leader_pid);
> + nulls[28] = false;
> + }
> + }
> }
>
> I'm slightly concerned that there could be overhead of executing
> GetLeaderApplyWorkerPid () for every backend process except for parallel
> query workers. The number of such backends could be large and
> GetLeaderApplyWorkerPid() acquires the lwlock. For example, does it make
> sense to check (st_backendType == B_BG_WORKER) before calling
> GetLeaderApplyWorkerPid()? Or it might not be a problem since it's
> LogicalRepWorkerLock which is not likely to be contended.
Thanks for the comment and I think your suggestion makes sense.
I have added the check before getting the leader pid. Here is the new version patch.
Best regards,
Hou zj
Attachments:
[application/octet-stream] v83-0001-Display-the-leader-apply-worker-s-PID-for-parall.patch (16.6K, ../../OS0PR01MB5716D8579FBE72BDEE17184194C69@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v83-0001-Display-the-leader-apply-worker-s-PID-for-parall.patch)
download | inline diff:
From d912cfe0901dc210b2b584e7d0ede553cf744dfd Mon Sep 17 00:00:00 2001
From: "houzj.fnst" <[email protected]>
Date: Thu, 6 Oct 2022 14:42:24 +0800
Subject: [PATCH v83] Display the leader apply worker's PID for parallel apply
workers.
Add leader_pid to pg_stat_subscription. leader_pid is the process ID of
the leader apply worker if this process is a parallel apply worker. If
this field is NULL, it indicates that the process is a leader apply
worker or a synchronization worker. The new column makes it easier to
distinguish parallel apply workers from other kinds of workers and helps
to identify the leader for the parallel workers corresponding to a
particular subscription.
Additionally, update the leader_pid column in pg_stat_activity to
display the PID of the leader apply worker for parallel apply workers.
Author: Hou Zhijie
Reviewed-by: Peter Smith, Sawada Masahiko, Amit Kapila
Discussion: https://postgr.es/m/CAA4eK1+wyN6zpaHUkCLorEWNx75MG0xhMwcFhvjqm2KURZEAGw@mail.gmail.com
---
doc/src/sgml/logical-replication.sgml | 3 +-
doc/src/sgml/monitoring.sgml | 36 ++++++++----
src/backend/catalog/system_views.sql | 1 +
.../replication/logical/applyparallelworker.c | 6 +-
src/backend/replication/logical/launcher.c | 64 ++++++++++++++++------
src/backend/utils/adt/pgstatfuncs.c | 21 +++++--
src/include/catalog/pg_proc.dat | 6 +-
src/include/replication/logicallauncher.h | 2 +
src/include/replication/worker_internal.h | 4 +-
src/test/regress/expected/rules.out | 3 +-
10 files changed, 104 insertions(+), 42 deletions(-)
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 54f48be..f4b4e64 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1692,7 +1692,8 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
subscription. A disabled subscription or a crashed subscription will have
zero rows in this view. If the initial data synchronization of any
table is in progress, there will be additional workers for the tables
- being synchronized.
+ being synchronized. Moreover, if the streaming transaction is applied in
+ parallel, there may be additional parallel apply workers.
</para>
</sect1>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 358d2ff..e3a783a 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -743,9 +743,11 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<structfield>leader_pid</structfield> <type>integer</type>
</para>
<para>
- Process ID of the parallel group leader, if this process is a
- parallel query worker. <literal>NULL</literal> if this process is a
- parallel group leader or does not participate in parallel query.
+ Process ID of the parallel group leader if this process is a parallel
+ query worker, or process ID of the leader apply worker if this process
+ is a parallel apply worker. <literal>NULL</literal> indicates that this
+ process is a parallel group leader or leader apply worker, or does not
+ participate in any parallel operation.
</para></entry>
</row>
@@ -3208,11 +3210,22 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<row>
<entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>leader_pid</structfield> <type>integer</type>
+ </para>
+ <para>
+ Process ID of the leader apply worker if this process is a parallel
+ apply worker; NULL if this process is a leader apply worker or a
+ synchronization worker
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
<structfield>relid</structfield> <type>oid</type>
</para>
<para>
- OID of the relation that the worker is synchronizing; null for the
- main apply worker
+ OID of the relation that the worker is synchronizing; NULL for the
+ leader apply worker and parallel apply workers
</para></entry>
</row>
@@ -3222,7 +3235,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Last write-ahead log location received, the initial value of
- this field being 0
+ this field being 0; NULL for parallel apply workers
</para></entry>
</row>
@@ -3231,7 +3244,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_send_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Send time of last message received from origin WAL sender
+ Send time of last message received from origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3240,7 +3254,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>last_msg_receipt_time</structfield> <type>timestamp with time zone</type>
</para>
<para>
- Receipt time of last message received from origin WAL sender
+ Receipt time of last message received from origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3249,7 +3264,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<structfield>latest_end_lsn</structfield> <type>pg_lsn</type>
</para>
<para>
- Last write-ahead log location reported to origin WAL sender
+ Last write-ahead log location reported to origin WAL sender; NULL for
+ parallel apply workers
</para></entry>
</row>
@@ -3259,7 +3275,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
</para>
<para>
Time of last write-ahead log location reported to origin WAL
- sender
+ sender; NULL for parallel apply workers
</para></entry>
</row>
</tbody>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index d2a8c82..8608e3f 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -948,6 +948,7 @@ CREATE VIEW pg_stat_subscription AS
su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3dfcff2..3579e70 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -849,7 +849,7 @@ LogicalParallelApplyLoop(shm_mq_handle *mqh)
static void
pa_shutdown(int code, Datum arg)
{
- SendProcSignal(MyLogicalRepWorker->apply_leader_pid,
+ SendProcSignal(MyLogicalRepWorker->leader_pid,
PROCSIG_PARALLEL_APPLY_MESSAGE,
InvalidBackendId);
@@ -932,7 +932,7 @@ ParallelApplyWorkerMain(Datum main_arg)
error_mqh = shm_mq_attach(mq, seg, NULL);
pq_redirect_to_shm_mq(seg, error_mqh);
- pq_set_parallel_leader(MyLogicalRepWorker->apply_leader_pid,
+ pq_set_parallel_leader(MyLogicalRepWorker->leader_pid,
InvalidBackendId);
MyLogicalRepWorker->last_send_time = MyLogicalRepWorker->last_recv_time =
@@ -950,7 +950,7 @@ ParallelApplyWorkerMain(Datum main_arg)
* The parallel apply worker doesn't need to monopolize this replication
* origin which was already acquired by its leader process.
*/
- replorigin_session_setup(originid, MyLogicalRepWorker->apply_leader_pid);
+ replorigin_session_setup(originid, MyLogicalRepWorker->leader_pid);
replorigin_session_origin = originid;
CommitTransactionCommand();
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index afb7acd..27e5856 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -410,7 +410,7 @@ retry:
worker->relstate = SUBREL_STATE_UNKNOWN;
worker->relstate_lsn = InvalidXLogRecPtr;
worker->stream_fileset = NULL;
- worker->apply_leader_pid = is_parallel_apply_worker ? MyProcPid : InvalidPid;
+ worker->leader_pid = is_parallel_apply_worker ? MyProcPid : InvalidPid;
worker->parallel_apply = is_parallel_apply_worker;
worker->last_lsn = InvalidXLogRecPtr;
TIMESTAMP_NOBEGIN(worker->last_send_time);
@@ -732,7 +732,7 @@ logicalrep_worker_cleanup(LogicalRepWorker *worker)
worker->userid = InvalidOid;
worker->subid = InvalidOid;
worker->relid = InvalidOid;
- worker->apply_leader_pid = InvalidPid;
+ worker->leader_pid = InvalidPid;
worker->parallel_apply = false;
}
@@ -1067,12 +1067,40 @@ IsLogicalLauncher(void)
}
/*
+ * Return the pid of the leader apply worker if the given pid is the pid of a
+ * parallel apply worker, otherwise, return InvalidPid.
+ */
+pid_t
+GetLeaderApplyWorkerPid(pid_t pid)
+{
+ int leader_pid = InvalidPid;
+ int i;
+
+ LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
+
+ for (i = 0; i < max_logical_replication_workers; i++)
+ {
+ LogicalRepWorker *w = &LogicalRepCtx->workers[i];
+
+ if (isParallelApplyWorker(w) && w->proc && pid == w->proc->pid)
+ {
+ leader_pid = w->leader_pid;
+ break;
+ }
+ }
+
+ LWLockRelease(LogicalRepWorkerLock);
+
+ return leader_pid;
+}
+
+/*
* Returns state of the subscriptions.
*/
Datum
pg_stat_get_subscription(PG_FUNCTION_ARGS)
{
-#define PG_STAT_GET_SUBSCRIPTION_COLS 8
+#define PG_STAT_GET_SUBSCRIPTION_COLS 9
Oid subid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
int i;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
@@ -1098,10 +1126,6 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
if (OidIsValid(subid) && worker.subid != subid)
continue;
- /* Skip if this is a parallel apply worker */
- if (isParallelApplyWorker(&worker))
- continue;
-
worker_pid = worker.proc->pid;
values[0] = ObjectIdGetDatum(worker.subid);
@@ -1110,26 +1134,32 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
else
nulls[1] = true;
values[2] = Int32GetDatum(worker_pid);
- if (XLogRecPtrIsInvalid(worker.last_lsn))
+
+ if (isParallelApplyWorker(&worker))
+ values[3] = Int32GetDatum(worker.leader_pid);
+ else
nulls[3] = true;
+
+ if (XLogRecPtrIsInvalid(worker.last_lsn))
+ nulls[4] = true;
else
- values[3] = LSNGetDatum(worker.last_lsn);
+ values[4] = LSNGetDatum(worker.last_lsn);
if (worker.last_send_time == 0)
- nulls[4] = true;
+ nulls[5] = true;
else
- values[4] = TimestampTzGetDatum(worker.last_send_time);
+ values[5] = TimestampTzGetDatum(worker.last_send_time);
if (worker.last_recv_time == 0)
- nulls[5] = true;
+ nulls[6] = true;
else
- values[5] = TimestampTzGetDatum(worker.last_recv_time);
+ values[6] = TimestampTzGetDatum(worker.last_recv_time);
if (XLogRecPtrIsInvalid(worker.reply_lsn))
- nulls[6] = true;
+ nulls[7] = true;
else
- values[6] = LSNGetDatum(worker.reply_lsn);
+ values[7] = LSNGetDatum(worker.reply_lsn);
if (worker.reply_time == 0)
- nulls[7] = true;
+ nulls[8] = true;
else
- values[7] = TimestampTzGetDatum(worker.reply_time);
+ values[8] = TimestampTzGetDatum(worker.reply_time);
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
values, nulls);
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 58bd136..6737493 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -25,6 +25,7 @@
#include "pgstat.h"
#include "postmaster/bgworker_internals.h"
#include "postmaster/postmaster.h"
+#include "replication/logicallauncher.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/acl.h"
@@ -409,9 +410,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
/*
* If a PGPROC entry was retrieved, display wait events and lock
- * group leader information if any. To avoid extra overhead, no
- * extra lock is being held, so there is no guarantee of
- * consistency across multiple rows.
+ * group leader or apply leader information if any. To avoid
+ * extra overhead, no extra lock is being held, so there is no
+ * guarantee of consistency across multiple rows.
*/
if (proc != NULL)
{
@@ -426,14 +427,24 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
/*
* Show the leader only for active parallel workers. This
- * leaves the field as NULL for the leader of a parallel
- * group.
+ * leaves the field as NULL for the leader of a parallel group
+ * or the leader of parallel apply workers.
*/
if (leader && leader->pid != beentry->st_procpid)
{
values[28] = Int32GetDatum(leader->pid);
nulls[28] = false;
}
+ else if (beentry->st_backendType == B_BG_WORKER)
+ {
+ int leader_pid = GetLeaderApplyWorkerPid(beentry->st_procpid);
+
+ if (leader_pid != InvalidPid)
+ {
+ values[28] = Int32GetDatum(leader_pid);
+ nulls[28] = false;
+ }
+ }
}
if (wait_event_type)
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3810de7..86eb8e8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5430,9 +5430,9 @@
proname => 'pg_stat_get_subscription', prorows => '10', proisstrict => 'f',
proretset => 't', provolatile => 's', proparallel => 'r',
prorettype => 'record', proargtypes => 'oid',
- proallargtypes => '{oid,oid,oid,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
- proargmodes => '{i,o,o,o,o,o,o,o,o}',
- proargnames => '{subid,subid,relid,pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
+ proallargtypes => '{oid,oid,oid,int4,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{subid,subid,relid,pid,leader_pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
prosrc => 'pg_stat_get_subscription' },
{ oid => '2026', descr => 'statistics: current backend PID',
proname => 'pg_backend_pid', provolatile => 's', proparallel => 'r',
diff --git a/src/include/replication/logicallauncher.h b/src/include/replication/logicallauncher.h
index c85593a..360e987 100644
--- a/src/include/replication/logicallauncher.h
+++ b/src/include/replication/logicallauncher.h
@@ -27,4 +27,6 @@ extern void AtEOXact_ApplyLauncher(bool isCommit);
extern bool IsLogicalLauncher(void);
+extern pid_t GetLeaderApplyWorkerPid(pid_t pid);
+
#endif /* LOGICALLAUNCHER_H */
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index db891ee..dc87a4e 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -71,7 +71,7 @@ typedef struct LogicalRepWorker
* PID of leader apply worker if this slot is used for a parallel apply
* worker, InvalidPid otherwise.
*/
- pid_t apply_leader_pid;
+ pid_t leader_pid;
/* Indicates whether apply can be performed in parallel. */
bool parallel_apply;
@@ -303,7 +303,7 @@ extern void pa_decr_and_wait_stream_block(void);
extern void pa_xact_finish(ParallelApplyWorkerInfo *winfo,
XLogRecPtr remote_lsn);
-#define isParallelApplyWorker(worker) ((worker)->apply_leader_pid != InvalidPid)
+#define isParallelApplyWorker(worker) ((worker)->leader_pid != InvalidPid)
static inline bool
am_tablesync_worker(void)
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index a969ae6..05eec2a 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2094,6 +2094,7 @@ pg_stat_ssl| SELECT s.pid,
pg_stat_subscription| SELECT su.oid AS subid,
su.subname,
st.pid,
+ st.leader_pid,
st.relid,
st.received_lsn,
st.last_msg_send_time,
@@ -2101,7 +2102,7 @@ pg_stat_subscription| SELECT su.oid AS subid,
st.latest_end_lsn,
st.latest_end_time
FROM (pg_subscription su
- LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
+ LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, leader_pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid)));
pg_stat_subscription_stats| SELECT ss.subid,
s.subname,
ss.apply_error_count,
--
2.7.2.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 02:21 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 03:32 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 03:37 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 06:46 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-17 09:14 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-17 14:37 ` Masahiko Sawada <[email protected]>
2023-01-18 04:35 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Masahiko Sawada @ 2023-01-17 14:37 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Peter Smith <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Amit Kapila <[email protected]>
On Tue, Jan 17, 2023 at 6:14 PM [email protected]
<[email protected]> wrote:
>
> On Tuesday, January 17, 2023 2:46 PM Masahiko Sawada <[email protected]> wrote:
> >
> > On Tue, Jan 17, 2023 at 12:37 PM [email protected]
> > <[email protected]> wrote:
> > > Attach the new version 0001 patch which addressed all other comments.
> > >
> >
> > Thank you for updating the patch. Here is one comment:
> >
> > @@ -426,14 +427,24 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
> >
> > /*
> > * Show the leader only for active parallel
> > workers. This
> > - * leaves the field as NULL for the
> > leader of a parallel
> > - * group.
> > + * leaves the field as NULL for the
> > leader of a parallel group
> > + * or the leader of parallel apply workers.
> > */
> > if (leader && leader->pid !=
> > beentry->st_procpid)
> > {
> > values[28] =
> > Int32GetDatum(leader->pid);
> > nulls[28] = false;
> > }
> > + else
> > + {
> > + int
> > leader_pid = GetLeaderApplyWorkerPid(beentry->st_procpid);
> > +
> > + if (leader_pid != InvalidPid)
> > + {
> > + values[28] =
> > Int32GetDatum(leader_pid);
> > + nulls[28] = false;
> > + }
> > + }
> > }
> >
> > I'm slightly concerned that there could be overhead of executing
> > GetLeaderApplyWorkerPid () for every backend process except for parallel
> > query workers. The number of such backends could be large and
> > GetLeaderApplyWorkerPid() acquires the lwlock. For example, does it make
> > sense to check (st_backendType == B_BG_WORKER) before calling
> > GetLeaderApplyWorkerPid()? Or it might not be a problem since it's
> > LogicalRepWorkerLock which is not likely to be contended.
>
> Thanks for the comment and I think your suggestion makes sense.
> I have added the check before getting the leader pid. Here is the new version patch.
Thank you for updating the patch. Looks good to me.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 02:21 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 03:32 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 03:37 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 06:46 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-17 09:14 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 14:37 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-01-18 04:35 ` Amit Kapila <[email protected]>
2023-01-18 04:48 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-01-18 04:35 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: [email protected] <[email protected]>; Peter Smith <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Tue, Jan 17, 2023 at 8:07 PM Masahiko Sawada <[email protected]> wrote:
>
> On Tue, Jan 17, 2023 at 6:14 PM [email protected]
> <[email protected]> wrote:
> >
> > On Tuesday, January 17, 2023 2:46 PM Masahiko Sawada <[email protected]> wrote:
> > >
> > > On Tue, Jan 17, 2023 at 12:37 PM [email protected]
> > > <[email protected]> wrote:
> > > I'm slightly concerned that there could be overhead of executing
> > > GetLeaderApplyWorkerPid () for every backend process except for parallel
> > > query workers. The number of such backends could be large and
> > > GetLeaderApplyWorkerPid() acquires the lwlock. For example, does it make
> > > sense to check (st_backendType == B_BG_WORKER) before calling
> > > GetLeaderApplyWorkerPid()? Or it might not be a problem since it's
> > > LogicalRepWorkerLock which is not likely to be contended.
> >
> > Thanks for the comment and I think your suggestion makes sense.
> > I have added the check before getting the leader pid. Here is the new version patch.
>
> Thank you for updating the patch. Looks good to me.
>
Pushed.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 02:21 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 03:32 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 03:37 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 06:46 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-17 09:14 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 14:37 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-18 04:35 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-18 04:48 ` [email protected] <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: [email protected] @ 2023-01-18 04:48 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; Masahiko Sawada <[email protected]>; +Cc: [email protected] <[email protected]>; Peter Smith <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Wed, Jan 18, 2023 12:36 PM Amit Kapila <[email protected]> wrote:
> On Tue, Jan 17, 2023 at 8:07 PM Masahiko Sawada <[email protected]>
> wrote:
> >
> > On Tue, Jan 17, 2023 at 6:14 PM [email protected]
> > <[email protected]> wrote:
> > >
> > > On Tuesday, January 17, 2023 2:46 PM Masahiko Sawada
> <[email protected]> wrote:
> > > >
> > > > On Tue, Jan 17, 2023 at 12:37 PM [email protected]
> > > > <[email protected]> wrote:
> > > > I'm slightly concerned that there could be overhead of executing
> > > > GetLeaderApplyWorkerPid () for every backend process except for parallel
> > > > query workers. The number of such backends could be large and
> > > > GetLeaderApplyWorkerPid() acquires the lwlock. For example, does it
> make
> > > > sense to check (st_backendType == B_BG_WORKER) before calling
> > > > GetLeaderApplyWorkerPid()? Or it might not be a problem since it's
> > > > LogicalRepWorkerLock which is not likely to be contended.
> > >
> > > Thanks for the comment and I think your suggestion makes sense.
> > > I have added the check before getting the leader pid. Here is the new
> version patch.
> >
> > Thank you for updating the patch. Looks good to me.
> >
>
> Pushed.
Rebased and attach remaining patches for reviewing.
Regards,
Wang Wei
Attachments:
[application/octet-stream] v84-0001-Stop-extra-worker-if-GUC-was-changed.patch (4.2K, ../../OS3PR01MB6275E91D744E9A3BBAD6ABBF9EC79@OS3PR01MB6275.jpnprd01.prod.outlook.com/2-v84-0001-Stop-extra-worker-if-GUC-was-changed.patch)
download | inline diff:
From 24e79a2f2d19b25df801cf756f88e5f9bbe24ba1 Mon Sep 17 00:00:00 2001
From: sherlockcpp <[email protected]>
Date: Sat, 17 Dec 2022 20:43:21 +0800
Subject: [PATCH v84 1/3] Stop extra worker if GUC was changed
If the max_parallel_apply_workers_per_subscription is changed to a
lower value, try to stop free workers in the pool to keep the number of
workers lower than half of the max_parallel_apply_workers_per_subscription
---
.../replication/logical/applyparallelworker.c | 63 +++++++++++++++----
src/backend/replication/logical/worker.c | 7 +++
src/include/replication/worker_internal.h | 1 +
3 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3579e704fe..948c25c388 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -542,6 +542,25 @@ pa_find_worker(TransactionId xid)
return NULL;
}
+/*
+ * Stop the given parallel apply worker and free the corresponding info.
+ */
+static void
+pa_stop_worker(ParallelApplyWorkerInfo *winfo)
+{
+ int slot_no;
+ uint16 generation;
+
+ SpinLockAcquire(&winfo->shared->mutex);
+ generation = winfo->shared->logicalrep_worker_generation;
+ slot_no = winfo->shared->logicalrep_worker_slot_no;
+ SpinLockRelease(&winfo->shared->mutex);
+
+ logicalrep_pa_worker_stop(slot_no, generation);
+
+ pa_free_worker_info(winfo);
+}
+
/*
* Makes the worker available for reuse.
*
@@ -577,23 +596,45 @@ pa_free_worker(ParallelApplyWorkerInfo *winfo)
list_length(ParallelApplyWorkerPool) >
(max_parallel_apply_workers_per_subscription / 2))
{
- int slot_no;
- uint16 generation;
-
- SpinLockAcquire(&winfo->shared->mutex);
- generation = winfo->shared->logicalrep_worker_generation;
- slot_no = winfo->shared->logicalrep_worker_slot_no;
- SpinLockRelease(&winfo->shared->mutex);
+ pa_stop_worker(winfo);
+ return;
+ }
- logicalrep_pa_worker_stop(slot_no, generation);
+ winfo->in_use = false;
+ winfo->serialize_changes = false;
+}
- pa_free_worker_info(winfo);
+/*
+ * Try to stop parallel apply workers that are not in use to keep the number of
+ * workers lower than half of the max_parallel_apply_workers_per_subscription.
+ */
+void
+pa_stop_idle_workers(void)
+{
+ List *active_workers;
+ ListCell *lc;
+ int max_applyworkers = max_parallel_apply_workers_per_subscription / 2;
+ if (list_length(ParallelApplyWorkerPool) <= max_applyworkers)
return;
+
+ active_workers = list_copy(ParallelApplyWorkerPool);
+
+ foreach(lc, active_workers)
+ {
+ ParallelApplyWorkerInfo *winfo = (ParallelApplyWorkerInfo *) lfirst(lc);
+
+ if (winfo->in_use)
+ continue;
+
+ pa_stop_worker(winfo);
+
+ /* Recheck the number of workers. */
+ if (list_length(ParallelApplyWorkerPool) <= max_applyworkers)
+ break;
}
- winfo->in_use = false;
- winfo->serialize_changes = false;
+ list_free(active_workers);
}
/*
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index a0084c7ef6..7700bc268f 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -3632,6 +3632,13 @@ LogicalRepApplyLoop(XLogRecPtr last_received)
{
ConfigReloadPending = false;
ProcessConfigFile(PGC_SIGHUP);
+
+ /*
+ * Try to stop free workers in the pool in case the
+ * max_parallel_apply_workers_per_subscription is changed to a
+ * lower value.
+ */
+ pa_stop_idle_workers();
}
if (rc & WL_TIMEOUT)
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index dc87a4edd1..34e5006307 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -274,6 +274,7 @@ extern void set_apply_error_context_origin(char *originname);
/* Parallel apply worker setup and interactions */
extern void pa_allocate_worker(TransactionId xid);
extern ParallelApplyWorkerInfo *pa_find_worker(TransactionId xid);
+extern void pa_stop_idle_workers(void);
extern void pa_detach_all_error_mq(void);
extern bool pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes,
--
2.23.0.windows.1
[application/octet-stream] v84-0002-Add-GUC-stream_serialize_threshold-and-test-seri.patch (13.5K, ../../OS3PR01MB6275E91D744E9A3BBAD6ABBF9EC79@OS3PR01MB6275.jpnprd01.prod.outlook.com/3-v84-0002-Add-GUC-stream_serialize_threshold-and-test-seri.patch)
download | inline diff:
From 539237e84257768ba5bbdb491eb79821f7e37996 Mon Sep 17 00:00:00 2001
From: Amit Kapila <[email protected]>
Date: Mon, 2 Jan 2023 15:37:25 +0530
Subject: [PATCH v84 2/3] Add GUC stream_serialize_threshold and test
serializing messages to disk.
---
doc/src/sgml/config.sgml | 32 ++++
.../replication/logical/applyparallelworker.c | 21 ++-
src/backend/replication/logical/worker.c | 9 ++
src/backend/utils/misc/guc_tables.c | 14 ++
src/include/replication/worker_internal.h | 4 +
src/test/subscription/t/015_stream.pl | 144 +++++++++++++++++-
6 files changed, 216 insertions(+), 8 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 89d53f2a64..4d766aa051 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11683,6 +11683,38 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
+ <varlistentry id="guc-stream-serialize-threshold" xreflabel="stream_serialize_threshold">
+ <term><varname>stream_serialize_threshold</varname> (<type>integer</type>)
+ <indexterm>
+ <primary><varname>stream_serialize_threshold</varname> configuration parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Forces the leader apply worker to serialize messages to files after
+ sending specified amount of streaming chunks to the parallel apply
+ worker. Setting this to zero serialize all messages. A value of
+ <literal>-1</literal> (the default) disables this feature. This is
+ intended to test serialization to files with
+ <literal>streaming = parallel</literal>.
+ </para>
+
+ <para>
+ When logical replication subscription <literal>streaming</literal>
+ parameter is set to <literal>parallel</literal>, the leader apply worker
+ sends messages to parallel workers with a timeout. By default, the
+ leader apply worker will serialize the remaining messages to files if
+ the timeout is exceeded. If this option is set to any value other than
+ <literal>-1</literal>, serialize to files even without timeout.
+ </para>
+
+ <para>
+ This parameter can only be set in the <filename>postgresql.conf</filename>
+ file or on the server command line.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</sect1>
<sect1 id="runtime-config-short">
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 948c25c388..3a2637e45b 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -254,6 +254,9 @@ static ParallelApplyWorkerInfo *stream_apply_worker = NULL;
/* A list to maintain subtransactions, if any. */
static List *subxactlist = NIL;
+/* GUC variable */
+int stream_serialize_threshold = -1;
+
static void pa_free_worker_info(ParallelApplyWorkerInfo *winfo);
static ParallelTransState pa_get_xact_state(ParallelApplyWorkerShared *wshared);
static PartialFileSetState pa_get_fileset_state(void);
@@ -1190,6 +1193,12 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ /* Force to serialize messages if stream_serialize_threshold is reached. */
+ if (stream_serialize_threshold != -1 &&
+ (stream_serialize_threshold == 0 ||
+ stream_serialize_threshold < parallel_stream_nchunks))
+ return false;
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
@@ -1228,12 +1237,7 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
startTime = GetCurrentTimestamp();
else if (TimestampDifferenceExceeds(startTime, GetCurrentTimestamp(),
SHM_SEND_TIMEOUT_MS))
- {
- ereport(LOG,
- (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
- winfo->shared->xid)));
return false;
- }
}
}
@@ -1247,6 +1251,13 @@ void
pa_switch_to_partial_serialize(ParallelApplyWorkerInfo *winfo,
bool stream_locked)
{
+ /* Reset parallel_stream_nchunks. */
+ parallel_stream_nchunks = 0;
+
+ ereport(LOG,
+ (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
+ winfo->shared->xid)));
+
/*
* The parallel apply worker could be stuck for some reason (say waiting
* on some lock by other backend), so stop trying to send data directly to
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 7700bc268f..07bbfacb2b 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -329,6 +329,12 @@ static TransactionId stream_xid = InvalidTransactionId;
*/
static uint32 parallel_stream_nchanges = 0;
+/*
+ * The number of streaming chunks sent by leader apply worker during one
+ * streamed transaction. This is only used when stream_serialize_threshold > 0.
+ */
+uint32 parallel_stream_nchunks = 0;
+
/*
* We enable skipping all data modification changes (INSERT, UPDATE, etc.) for
* the subscription if the remote transaction's finish LSN matches the subskiplsn.
@@ -1532,6 +1538,9 @@ apply_handle_stream_start(StringInfo s)
case TRANS_LEADER_SEND_TO_PARALLEL:
Assert(winfo);
+ if (stream_serialize_threshold > 0)
+ parallel_stream_nchunks++;
+
/*
* Once we start serializing the changes, the parallel apply
* worker will wait for the leader to release the stream lock
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 5025e80f89..15d3781459 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -61,6 +61,7 @@
#include "replication/logicallauncher.h"
#include "replication/slot.h"
#include "replication/syncrep.h"
+#include "replication/worker_internal.h"
#include "storage/bufmgr.h"
#include "storage/large_object.h"
#include "storage/pg_shmem.h"
@@ -3014,6 +3015,19 @@ struct config_int ConfigureNamesInt[] =
NULL, NULL, NULL
},
+ {
+ {"stream_serialize_threshold", PGC_SIGHUP, DEVELOPER_OPTIONS,
+ gettext_noop("Forces the leader apply worker to serialize messages "
+ "to files after sending specified amount of streaming "
+ "chunks in streaming parallel mode."),
+ gettext_noop("A value of -1 disables this feature."),
+ GUC_NOT_IN_SAMPLE
+ },
+ &stream_serialize_threshold,
+ -1, -1, INT_MAX,
+ NULL, NULL, NULL
+ },
+
{
{"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
gettext_noop("Sets the amount of time to wait before forcing "
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index 34e5006307..7f6a9f9821 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -225,6 +225,10 @@ extern PGDLLIMPORT LogicalRepWorker *MyLogicalRepWorker;
extern PGDLLIMPORT bool in_remote_transaction;
+extern PGDLLIMPORT int stream_serialize_threshold;
+
+extern PGDLLIMPORT uint32 parallel_stream_nchunks;
+
extern void logicalrep_worker_attach(int slot);
extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
bool only_running);
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8c0a..ddc00abca0 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -133,13 +133,20 @@ sub test_streaming
# Create publisher node
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
-$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_work_mem = 64kB');
+$node_publisher->append_conf(
+ 'postgresql.conf', qq(
+max_prepared_transactions = 10
+logical_decoding_work_mem = 64kB
+));
$node_publisher->start;
# Create subscriber node
my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->append_conf(
+ 'postgresql.conf', qq(
+max_prepared_transactions = 10
+));
$node_subscriber->start;
# Create some preexisting content on publisher
@@ -170,7 +177,7 @@ my $appname = 'tap_sub';
# Test using streaming mode 'on'
################################
$node_subscriber->safe_psql('postgres',
- "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (streaming = on)"
+ "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (streaming = on, two_phase = on)"
);
# Wait for initial table sync to finish
@@ -312,6 +319,137 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Test serializing messages to disk
+
+# Set stream_serialize_threshold to zero, so the messages will be serialized to disk.
+$node_subscriber->safe_psql('postgres',
+ 'ALTER SYSTEM SET stream_serialize_threshold = 0;');
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+# Serialize the COMMIT transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the PREPARE transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the ABORT top-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ ROLLBACK;
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0),
+ 'data replicated to subscriber by serializing messages to disk');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 SELECT i FROM generate_series(5001, 10000) s(i);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5000),
+ 'data replicated to subscriber by serializing messages to disk');
+
$node_subscriber->stop;
$node_publisher->stop;
--
2.23.0.windows.1
[application/octet-stream] v84-0003-Retry-to-apply-streaming-xact-only-in-apply-work.patch (21.1K, ../../OS3PR01MB6275E91D744E9A3BBAD6ABBF9EC79@OS3PR01MB6275.jpnprd01.prod.outlook.com/4-v84-0003-Retry-to-apply-streaming-xact-only-in-apply-work.patch)
download | inline diff:
From cd3ea77e453a67160f1aff8f81d0a77f8b504192 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Sun, 11 Dec 2022 19:16:34 +0800
Subject: [PATCH v84 3/3] Retry to apply streaming xact only in apply worker
When the subscription parameter is set streaming=parallel, the logic tries to
apply the streaming transaction using a parallel apply worker. If this
fails the parallel worker exits with an error.
In this case, retry applying the streaming transaction using the normal
streaming=on mode. This is done to avoid getting caught in a loop of the same
retry errors.
A new flag field "subretry" has been introduced to catalog "pg_subscription".
If there are any active parallel apply workers and the subscriber exits with an
error, this flag will be set true, and whenever the transaction is applied
successfully, this flag is reset false.
Now, when deciding how to apply a streaming transaction, the logic can know if
this transaction has previously failed or not (by checking the "subretry"
field).
Note: Since we add a new field 'subretry' to catalog 'pg_subscription' has been
expanded, we need bump catalog version.
---
doc/src/sgml/catalogs.sgml | 10 +
doc/src/sgml/logical-replication.sgml | 11 +-
doc/src/sgml/ref/create_subscription.sgml | 5 +
src/backend/catalog/pg_subscription.c | 1 +
src/backend/catalog/system_views.sql | 2 +-
src/backend/commands/subscriptioncmds.c | 1 +
.../replication/logical/applyparallelworker.c | 30 +++
src/backend/replication/logical/worker.c | 182 +++++++++++++-----
src/bin/pg_dump/pg_dump.c | 5 +-
src/include/catalog/pg_subscription.h | 7 +
src/include/replication/worker_internal.h | 2 +
src/test/subscription/t/015_stream.pl | 63 ++++++
12 files changed, 263 insertions(+), 56 deletions(-)
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index c1e4048054..d918327ec2 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -7948,6 +7948,16 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l
</para></entry>
</row>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>subretry</structfield> <type>bool</type>
+ </para>
+ <para>
+ True if previous change failed to be applied while there were any
+ active parallel apply workers, necessitating a retry.
+ </para></entry>
+ </row>
+
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>subconninfo</structfield> <type>text</type>
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index f4b4e641be..57e938f030 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1504,12 +1504,11 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
<para>
When the streaming mode is <literal>parallel</literal>, the finish LSN of
- failed transactions may not be logged. In that case, it may be necessary to
- change the streaming mode to <literal>on</literal> or <literal>off</literal> and
- cause the same conflicts again so the finish LSN of the failed transaction will
- be written to the server log. For the usage of finish LSN, please refer to <link
- linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION ...
- SKIP</command></link>.
+ failed transactions may not be logged. In that case, the failed transaction
+ will be retried in <literal>streaming = on</literal> mode. If it fails
+ again, the finish LSN of the failed transaction will be written to the
+ server log. For the usage of finish LSN, please refer to
+ <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION ... SKIP</command></link>.
</para>
</sect1>
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
index eba72c6af6..decd554457 100644
--- a/doc/src/sgml/ref/create_subscription.sgml
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -251,6 +251,11 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
transaction is committed. Note that if an error happens in a
parallel apply worker, the finish LSN of the remote transaction
might not be reported in the server log.
+ When applying streaming transactions, if a deadlock is detected, the
+ parallel apply worker will exit with an error. The
+ <literal>parallel</literal> mode is disregarded when retrying;
+ instead the transaction will be applied using <literal>on</literal>
+ mode.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index a56ae311c3..0eb5ffb3e1 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -71,6 +71,7 @@ GetSubscription(Oid subid, bool missing_ok)
sub->stream = subform->substream;
sub->twophasestate = subform->subtwophasestate;
sub->disableonerr = subform->subdisableonerr;
+ sub->retry = subform->subretry;
/* Get conninfo */
datum = SysCacheGetAttr(SUBSCRIPTIONOID,
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 8608e3fa5b..5171feae97 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1301,7 +1301,7 @@ REVOKE ALL ON pg_replication_origin_status FROM public;
REVOKE ALL ON pg_subscription FROM public;
GRANT SELECT (oid, subdbid, subskiplsn, subname, subowner, subenabled,
subbinary, substream, subtwophasestate, subdisableonerr,
- subslotname, subsynccommit, subpublications, suborigin)
+ subretry, subslotname, subsynccommit, subpublications, suborigin)
ON pg_subscription TO public;
CREATE VIEW pg_stat_subscription_stats AS
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index baff00dd74..b2053f79ee 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -636,6 +636,7 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
LOGICALREP_TWOPHASE_STATE_PENDING :
LOGICALREP_TWOPHASE_STATE_DISABLED);
values[Anum_pg_subscription_subdisableonerr - 1] = BoolGetDatum(opts.disableonerr);
+ values[Anum_pg_subscription_subretry - 1] = BoolGetDatum(false);
values[Anum_pg_subscription_subconninfo - 1] =
CStringGetTextDatum(conninfo);
if (opts.slot_name)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3a2637e45b..cabfe576d0 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -315,6 +315,17 @@ pa_can_start(void)
if (!AllTablesyncsReady())
return false;
+ /*
+ * Don't use parallel apply workers for retries, because it is possible
+ * that a deadlock was detected the last time we tried to apply a
+ * transaction using a parallel apply worker.
+ */
+ if (MySubscription->retry)
+ {
+ elog(DEBUG1, "parallel apply workers are not used for retries");
+ return false;
+ }
+
return true;
}
@@ -1680,3 +1691,22 @@ pa_xact_finish(ParallelApplyWorkerInfo *winfo, XLogRecPtr remote_lsn)
pa_free_worker(winfo);
}
+
+/* Check if any active parallel apply workers. */
+bool
+pa_have_active_worker(void)
+{
+ ListCell *lc;
+
+ foreach(lc, ParallelApplyWorkerPool)
+ {
+ ParallelApplyWorkerInfo *tmp_winfo;
+
+ tmp_winfo = (ParallelApplyWorkerInfo *) lfirst(lc);
+
+ if (tmp_winfo->in_use)
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 07bbfacb2b..3f1e863f3a 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -396,7 +396,7 @@ static void stream_close_file(void);
static void send_feedback(XLogRecPtr recvpos, bool force, bool requestReply);
-static void DisableSubscriptionAndExit(void);
+static void DisableSubscriptionOnError(void);
static void apply_handle_commit_internal(LogicalRepCommitData *commit_data);
static void apply_handle_insert_internal(ApplyExecutionData *edata,
@@ -433,6 +433,8 @@ static inline void reset_apply_error_context_info(void);
static TransApplyAction get_transaction_apply_action(TransactionId xid,
ParallelApplyWorkerInfo **winfo);
+static void set_subscription_retry(bool retry);
+
/*
* Return the name of the logical replication worker.
*/
@@ -1051,6 +1053,9 @@ apply_handle_commit(StringInfo s)
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(commit_data.end_lsn);
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_activity(STATE_IDLE, NULL);
reset_apply_error_context_info();
}
@@ -1160,6 +1165,9 @@ apply_handle_prepare(StringInfo s)
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(prepare_data.end_lsn);
@@ -1216,6 +1224,9 @@ apply_handle_commit_prepared(StringInfo s)
store_flush_position(prepare_data.end_lsn, XactLastCommitEnd);
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(prepare_data.end_lsn);
@@ -1277,6 +1288,9 @@ apply_handle_rollback_prepared(StringInfo s)
store_flush_position(rollback_data.rollback_end_lsn, XactLastCommitEnd);
in_remote_transaction = false;
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(rollback_data.rollback_end_lsn);
@@ -1402,6 +1416,9 @@ apply_handle_stream_prepare(StringInfo s)
break;
}
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_stat(false);
/* Process any tables that are being synchronized in parallel. */
@@ -1982,6 +1999,10 @@ apply_handle_stream_abort(StringInfo s)
break;
}
+ /* Reset the retry flag. */
+ if (toplevel_xact)
+ set_subscription_retry(false);
+
reset_apply_error_context_info();
}
@@ -2254,6 +2275,9 @@ apply_handle_stream_commit(StringInfo s)
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(commit_data.end_lsn);
+ /* Reset the retry flag. */
+ set_subscription_retry(false);
+
pgstat_report_activity(STATE_IDLE, NULL);
reset_apply_error_context_info();
@@ -4340,20 +4364,28 @@ start_table_sync(XLogRecPtr *origin_startpos, char **myslotname)
}
PG_CATCH();
{
+ /*
+ * Emit the error message, and recover from the error state to an idle
+ * state
+ */
+ HOLD_INTERRUPTS();
+
+ EmitErrorReport();
+ AbortOutOfAnyTransaction();
+ FlushErrorState();
+
+ RESUME_INTERRUPTS();
+
+ /* Report the worker failed during table synchronization */
+ pgstat_report_subscription_error(MySubscription->oid, false);
+
if (MySubscription->disableonerr)
- DisableSubscriptionAndExit();
- else
- {
- /*
- * Report the worker failed during table synchronization. Abort
- * the current transaction so that the stats message is sent in an
- * idle state.
- */
- AbortOutOfAnyTransaction();
- pgstat_report_subscription_error(MySubscription->oid, false);
+ DisableSubscriptionOnError();
- PG_RE_THROW();
- }
+ /* Set the retry flag. */
+ set_subscription_retry(true);
+
+ proc_exit(0);
}
PG_END_TRY();
@@ -4378,20 +4410,27 @@ start_apply(XLogRecPtr origin_startpos)
}
PG_CATCH();
{
+ /*
+ * Emit the error message, and recover from the error state to an idle
+ * state
+ */
+ HOLD_INTERRUPTS();
+
+ EmitErrorReport();
+ AbortOutOfAnyTransaction();
+ FlushErrorState();
+
+ RESUME_INTERRUPTS();
+
+ /* Report the worker failed while applying changes */
+ pgstat_report_subscription_error(MySubscription->oid,
+ !am_tablesync_worker());
+
if (MySubscription->disableonerr)
- DisableSubscriptionAndExit();
- else
- {
- /*
- * Report the worker failed while applying changes. Abort the
- * current transaction so that the stats message is sent in an
- * idle state.
- */
- AbortOutOfAnyTransaction();
- pgstat_report_subscription_error(MySubscription->oid, !am_tablesync_worker());
+ DisableSubscriptionOnError();
- PG_RE_THROW();
- }
+ /* Set the retry flag. */
+ set_subscription_retry(true);
}
PG_END_TRY();
}
@@ -4667,39 +4706,20 @@ ApplyWorkerMain(Datum main_arg)
}
/*
- * After error recovery, disable the subscription in a new transaction
- * and exit cleanly.
+ * Disable the subscription in a new transaction.
*/
static void
-DisableSubscriptionAndExit(void)
+DisableSubscriptionOnError(void)
{
- /*
- * Emit the error message, and recover from the error state to an idle
- * state
- */
- HOLD_INTERRUPTS();
-
- EmitErrorReport();
- AbortOutOfAnyTransaction();
- FlushErrorState();
-
- RESUME_INTERRUPTS();
-
- /* Report the worker failed during either table synchronization or apply */
- pgstat_report_subscription_error(MyLogicalRepWorker->subid,
- !am_tablesync_worker());
-
/* Disable the subscription */
StartTransactionCommand();
DisableSubscription(MySubscription->oid);
CommitTransactionCommand();
- /* Notify the subscription has been disabled and exit */
+ /* Notify the subscription has been disabled */
ereport(LOG,
errmsg("subscription \"%s\" has been disabled because of an error",
MySubscription->name));
-
- proc_exit(0);
}
/*
@@ -5052,3 +5072,71 @@ get_transaction_apply_action(TransactionId xid, ParallelApplyWorkerInfo **winfo)
return TRANS_LEADER_APPLY;
}
}
+
+/*
+ * Set subretry of pg_subscription catalog.
+ *
+ * If retry is true, subscriber is about to exit with an error. Otherwise, it
+ * means that the transaction was applied successfully.
+ */
+static void
+set_subscription_retry(bool retry)
+{
+ Relation rel;
+ HeapTuple tup;
+ bool started_tx = false;
+ bool nulls[Natts_pg_subscription];
+ bool replaces[Natts_pg_subscription];
+ Datum values[Natts_pg_subscription];
+
+ /* Fast path - if no state change then nothing to do */
+ if (MySubscription->retry == retry)
+ return;
+
+ /* Fast path - skip for parallel apply workers */
+ if (am_parallel_apply_worker())
+ return;
+
+ /* Fast path - skip set retry if no active parallel apply workers */
+ if (retry && !pa_have_active_worker())
+ return;
+
+ if (!IsTransactionState())
+ {
+ StartTransactionCommand();
+ started_tx = true;
+ }
+
+ /* Look up the subscription in the catalog */
+ rel = table_open(SubscriptionRelationId, RowExclusiveLock);
+ tup = SearchSysCacheCopy1(SUBSCRIPTIONOID,
+ ObjectIdGetDatum(MySubscription->oid));
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "subscription \"%s\" does not exist", MySubscription->name);
+
+ LockSharedObject(SubscriptionRelationId, MySubscription->oid, 0,
+ AccessShareLock);
+
+ /* Form a new tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ /* Set subretry */
+ values[Anum_pg_subscription_subretry - 1] = BoolGetDatum(retry);
+ replaces[Anum_pg_subscription_subretry - 1] = true;
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
+ replaces);
+
+ /* Update the catalog. */
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ /* Cleanup. */
+ heap_freetuple(tup);
+ table_close(rel, NoLock);
+
+ if (started_tx)
+ CommitTransactionCommand();
+}
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 527c7651ab..2f6ec5d5ea 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -4560,8 +4560,9 @@ getSubscriptions(Archive *fout)
ntups = PQntuples(res);
/*
- * Get subscription fields. We don't include subskiplsn in the dump as
- * after restoring the dump this value may no longer be relevant.
+ * Get subscription fields. We don't include subskiplsn and subretry in
+ * the dump as after restoring the dump this value may no longer be
+ * relevant.
*/
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index b0f2a1705d..8edbbca442 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -88,6 +88,11 @@ CATALOG(pg_subscription,6100,SubscriptionRelationId) BKI_SHARED_RELATION BKI_ROW
bool subdisableonerr; /* True if a worker error should cause the
* subscription to be disabled */
+ bool subretry BKI_DEFAULT(f); /* True if previous change failed
+ * to be applied while there were
+ * any active parallel apply
+ * workers */
+
#ifdef CATALOG_VARLEN /* variable-length fields start here */
/* Connection string to the publisher */
text subconninfo BKI_FORCE_NOT_NULL;
@@ -131,6 +136,8 @@ typedef struct Subscription
bool disableonerr; /* Indicates if the subscription should be
* automatically disabled if a worker error
* occurs */
+ bool retry; /* Indicates if previous change failed to be
+ * applied using a parallel apply worker */
char *conninfo; /* Connection string to the publisher */
char *slotname; /* Name of the replication slot */
char *synccommit; /* Synchronous commit setting for worker */
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index 7f6a9f9821..2e466e0cdc 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -308,6 +308,8 @@ extern void pa_decr_and_wait_stream_block(void);
extern void pa_xact_finish(ParallelApplyWorkerInfo *winfo,
XLogRecPtr remote_lsn);
+extern bool pa_have_active_worker(void);
+
#define isParallelApplyWorker(worker) ((worker)->leader_pid != InvalidPid)
static inline bool
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index ddc00abca0..48c412130b 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -74,8 +74,16 @@ sub test_streaming
'check extra columns contain local defaults');
# Test the streaming in binary mode
+ my $oldpid = $node_publisher->safe_psql('postgres',
+ "SELECT pid FROM pg_stat_replication WHERE application_name = '$appname' AND state = 'streaming';"
+ );
$node_subscriber->safe_psql('postgres',
"ALTER SUBSCRIPTION tap_sub SET (binary = on)");
+ $node_publisher->poll_query_until('postgres',
+ "SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = '$appname' AND state = 'streaming';"
+ )
+ or die
+ "Timed out while waiting for apply to restart after changing SUBSCRIPTION";
# Check the subscriber log from now on.
$offset = -s $node_subscriber->logfile;
@@ -450,6 +458,61 @@ $result =
is($result, qq(5000),
'data replicated to subscriber by serializing messages to disk');
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# ============================================================================
+# Test re-apply a failed streaming transaction using the leader apply
+# worker and apply subsequent streaming transaction using the parallel apply
+# worker after this retry succeeds.
+# ============================================================================
+
+$node_subscriber->safe_psql('postgres',
+ "CREATE UNIQUE INDEX idx_tab on test_tab_2(a)");
+
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', qq{
+BEGIN;
+INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i);
+INSERT INTO test_tab_2 values(1);
+COMMIT;});
+
+# Check if the parallel apply worker is not started because the above
+# transaction failed to be applied.
+$node_subscriber->wait_for_log(
+ qr/DEBUG: ( [A-Z0-9]+:)? parallel apply workers are not used for retries/,
+ $offset);
+
+# Drop the unique index on the subscriber, now it works.
+$node_subscriber->safe_psql('postgres', "DROP INDEX idx_tab");
+
+# Wait for this streaming transaction to be applied in the apply worker.
+$node_publisher->wait_for_catchup($appname);
+
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(5001), 'data replicated to subscriber after dropping index');
+
+# After successfully retrying to apply a failed streaming transaction, apply
+# the following streaming transaction using the parallel apply worker.
+
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(5001, 10000) s(i)");
+
+check_parallel_log($node_subscriber, $offset, 1, 'COMMIT');
+
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(10001),
+ 'data replicated to subscriber using the parallel apply worker');
+
$node_subscriber->stop;
$node_publisher->stop;
--
2.23.0.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-13 06:19 ` Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Peter Smith @ 2023-01-13 06:19 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
Here are some review comments for patch v79-0002.
======
General
1.
I saw that earlier in this thread Hou-san [1] and Amit [2] also seemed
to say there is not much point for this patch.
So I wanted to +1 that same opinion.
I feel this patch just adds more complexity for almost no gain:
- reducing the 'max_apply_workers_per_suibscription' seems not very
common in the first place.
- even when the GUC is reduced, at that point in time all the workers
might be in use so there may be nothing that can be immediately done.
- IIUC the excess workers (for a reduced GUC) are going to get freed
naturally anyway over time as more transactions are completed so the
pool size will reduce accordingly.
~
OTOH some refactoring parts of this patch (e.g. the new pa_stop_worker
function) look better to me. I would keep those ones but remove all
the pa_stop_idle_workers function/call.
*** NOTE: The remainder of these review comments are maybe only
relevant if you are going to keep this pa_stop_idle_workers
behaviour...
======
Commit message
2.
If the max_parallel_apply_workers_per_subscription is changed to a
lower value, try to stop free workers in the pool to keep the number of
workers lower than half of the max_parallel_apply_workers_per_subscription
SUGGESTION
If the GUC max_parallel_apply_workers_per_subscription is changed to a
lower value, try to stop unused workers to keep the pool size lower
than half of max_parallel_apply_workers_per_subscription.
======
.../replication/logical/applyparallelworker.c
3. pa_free_worker
if (winfo->serialize_changes ||
list_length(ParallelApplyWorkerPool) >
(max_parallel_apply_workers_per_subscription / 2))
{
pa_stop_worker(winfo);
return;
}
winfo->in_use = false;
winfo->serialize_changes = false;
~
IMO the above code can be more neatly written using if/else because
then there is only one return point, and there is a place to write the
explanatory comment about the else.
SUGGESTION
if (winfo->serialize_changes ||
list_length(ParallelApplyWorkerPool) >
(max_parallel_apply_workers_per_subscription / 2))
{
pa_stop_worker(winfo);
}
else
{
/* Don't stop the worker. Only mark it available for re-use. */
winfo->in_use = false;
winfo->serialize_changes = false;
}
======
src/backend/replication/logical/worker.c
4. pa_stop_idle_workers
/*
* Try to stop parallel apply workers that are not in use to keep the number of
* workers lower than half of the max_parallel_apply_workers_per_subscription.
*/
void
pa_stop_idle_workers(void)
{
List *active_workers;
ListCell *lc;
int max_applyworkers = max_parallel_apply_workers_per_subscription / 2;
if (list_length(ParallelApplyWorkerPool) <= max_applyworkers)
return;
active_workers = list_copy(ParallelApplyWorkerPool);
foreach(lc, active_workers)
{
ParallelApplyWorkerInfo *winfo = (ParallelApplyWorkerInfo *) lfirst(lc);
pa_stop_worker(winfo);
/* Recheck the number of workers. */
if (list_length(ParallelApplyWorkerPool) <= max_applyworkers)
break;
}
list_free(active_workers);
}
~
4a. function comment
SUGGESTION
Try to keep the worker pool size lower than half of the
max_parallel_apply_workers_per_subscription.
~
4b. function name
This is not stopping all idle workers, so maybe a more meaningful name
for this function is something more like "pa_reduce_workerpool"
~
4c.
IMO the "max_applyworkers" var is a misleading name. Maybe something
like "goal_poolsize" is better?
~
4d.
Maybe I misunderstand the logic for the pool, but shouldn't this be
checking the winfo->in_use flag before blindly stopping each worker?
======
src/backend/replication/logical/worker.c
5.
@@ -3630,6 +3630,13 @@ LogicalRepApplyLoop(XLogRecPtr last_received)
{
ConfigReloadPending = false;
ProcessConfigFile(PGC_SIGHUP);
+
+ /*
+ * Try to stop free workers in the pool in case the
+ * max_parallel_apply_workers_per_subscription is changed to a
+ * lower value.
+ */
+ pa_stop_idle_workers();
}
5a.
SUGGESTED COMMENT
If max_parallel_apply_workers_per_subscription is changed to a lower
value, try to reduce the worker pool to match.
~
5b.
Instead of unconditionally calling pa_stop_idle_workers, shouldn't
this code compare the value of
max_parallel_apply_workers_per_subscription before/after the
ProcessConfigFile so it only calls if the GUC was lowered?
------
[1] Hou-san - https://www.postgresql.org/message-id/OS0PR01MB5716E527412A3481F90B4397941A9%40OS0PR01MB5716.jpnprd0...
[2] Amit - https://www.postgresql.org/message-id/CAA4eK1J%3D9m-VNRMHCqeG8jpX0CTn3Ciad2o4H-ogrZMDJ3tn4w%40mail.g...
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-18 06:39 ` Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-01-18 06:39 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; shveta malik <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Fri, Jan 13, 2023 at 11:50 AM Peter Smith <[email protected]> wrote:
>
> Here are some review comments for patch v79-0002.
>
So, this is about the latest v84-0001-Stop-extra-worker-if-GUC-was-changed.
> ======
>
> General
>
> 1.
>
> I saw that earlier in this thread Hou-san [1] and Amit [2] also seemed
> to say there is not much point for this patch.
>
> So I wanted to +1 that same opinion.
>
> I feel this patch just adds more complexity for almost no gain:
> - reducing the 'max_apply_workers_per_suibscription' seems not very
> common in the first place.
> - even when the GUC is reduced, at that point in time all the workers
> might be in use so there may be nothing that can be immediately done.
> - IIUC the excess workers (for a reduced GUC) are going to get freed
> naturally anyway over time as more transactions are completed so the
> pool size will reduce accordingly.
>
I am still not sure if it is worth pursuing this patch because of the
above reasons. I don't think it would be difficult to add this even at
a later point in time if we really see a use case for this.
Sawada-San, IIRC, you raised this point. What do you think?
The other point I am wondering is whether we can have a different way
to test partial serialization apart from introducing another developer
GUC (stream_serialize_threshold). One possibility could be that we can
have a subscription option (parallel_send_timeout or something like
that) with some default value (current_timeout used in the patch)
which will be used only when streaming = parallel. Users may want to
wait for more time before serialization starts depending on the
workload (say when resource usage is high on a subscriber-side
machine, or there are concurrent long-running transactions that can
block parallel apply for a bit longer time). I know with this as well
it may not be straightforward to test the functionality because we
can't be sure how many changes would be required for a timeout to
occur. This is just for brainstorming other options to test the
partial serialization functionality.
Thoughts?
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-19 05:40 ` Amit Kapila <[email protected]>
2023-01-19 10:14 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 2 replies; 105+ messages in thread
From: Amit Kapila @ 2023-01-19 05:40 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; shveta malik <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Wed, Jan 18, 2023 at 12:09 PM Amit Kapila <[email protected]> wrote:
>
> On Fri, Jan 13, 2023 at 11:50 AM Peter Smith <[email protected]> wrote:
> >
> > Here are some review comments for patch v79-0002.
> >
>
> So, this is about the latest v84-0001-Stop-extra-worker-if-GUC-was-changed.
>
> >
> > I feel this patch just adds more complexity for almost no gain:
> > - reducing the 'max_apply_workers_per_suibscription' seems not very
> > common in the first place.
> > - even when the GUC is reduced, at that point in time all the workers
> > might be in use so there may be nothing that can be immediately done.
> > - IIUC the excess workers (for a reduced GUC) are going to get freed
> > naturally anyway over time as more transactions are completed so the
> > pool size will reduce accordingly.
> >
>
> I am still not sure if it is worth pursuing this patch because of the
> above reasons. I don't think it would be difficult to add this even at
> a later point in time if we really see a use case for this.
> Sawada-San, IIRC, you raised this point. What do you think?
>
> The other point I am wondering is whether we can have a different way
> to test partial serialization apart from introducing another developer
> GUC (stream_serialize_threshold). One possibility could be that we can
> have a subscription option (parallel_send_timeout or something like
> that) with some default value (current_timeout used in the patch)
> which will be used only when streaming = parallel. Users may want to
> wait for more time before serialization starts depending on the
> workload (say when resource usage is high on a subscriber-side
> machine, or there are concurrent long-running transactions that can
> block parallel apply for a bit longer time). I know with this as well
> it may not be straightforward to test the functionality because we
> can't be sure how many changes would be required for a timeout to
> occur. This is just for brainstorming other options to test the
> partial serialization functionality.
>
Apart from the above, we can also have a subscription option to
specify parallel_shm_queue_size (queue_size used to determine the
queue between the leader and parallel worker) and that can be used for
this purpose. Basically, configuring it to a smaller value can help in
reducing the test time but still, it will not eliminate the need for
dependency on timing we have to wait before switching to partial
serialize mode. I think this can be used in production as well to tune
the performance depending on workload.
Yet another way is to use the existing parameter logical_decode_mode
[1]. If the value of logical_decoding_mode is 'immediate', then we can
immediately switch to partial serialize mode. This will eliminate the
dependency on timing. The one argument against using this is that it
won't be as clear as a separate parameter like
'stream_serialize_threshold' proposed by the patch but OTOH we already
have a few parameters that serve a different purpose when used on the
subscriber. For example, 'max_replication_slots' is used to define the
maximum number of replication slots on the publisher and the maximum
number of origins on subscribers. Similarly,
wal_retrieve_retry_interval' is used for different purposes on
subscriber and standby nodes.
[1] - https://www.postgresql.org/docs/devel/runtime-config-developer.html
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-19 10:14 ` shveta malik <[email protected]>
2023-01-19 10:22 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
1 sibling, 1 reply; 105+ messages in thread
From: shveta malik @ 2023-01-19 10:14 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Peter Smith <[email protected]>; [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; shveta malik <[email protected]>
On Thu, Jan 19, 2023 at 11:11 AM Amit Kapila <[email protected]> wrote:
>
> On Wed, Jan 18, 2023 at 12:09 PM Amit Kapila <[email protected]> wrote:
> >
> > On Fri, Jan 13, 2023 at 11:50 AM Peter Smith <[email protected]> wrote:
> > >
> > > Here are some review comments for patch v79-0002.
> > >
> >
> > So, this is about the latest v84-0001-Stop-extra-worker-if-GUC-was-changed.
> >
> > >
> > > I feel this patch just adds more complexity for almost no gain:
> > > - reducing the 'max_apply_workers_per_suibscription' seems not very
> > > common in the first place.
> > > - even when the GUC is reduced, at that point in time all the workers
> > > might be in use so there may be nothing that can be immediately done.
> > > - IIUC the excess workers (for a reduced GUC) are going to get freed
> > > naturally anyway over time as more transactions are completed so the
> > > pool size will reduce accordingly.
> > >
> >
> > I am still not sure if it is worth pursuing this patch because of the
> > above reasons. I don't think it would be difficult to add this even at
> > a later point in time if we really see a use case for this.
> > Sawada-San, IIRC, you raised this point. What do you think?
> >
> > The other point I am wondering is whether we can have a different way
> > to test partial serialization apart from introducing another developer
> > GUC (stream_serialize_threshold). One possibility could be that we can
> > have a subscription option (parallel_send_timeout or something like
> > that) with some default value (current_timeout used in the patch)
> > which will be used only when streaming = parallel. Users may want to
> > wait for more time before serialization starts depending on the
> > workload (say when resource usage is high on a subscriber-side
> > machine, or there are concurrent long-running transactions that can
> > block parallel apply for a bit longer time). I know with this as well
> > it may not be straightforward to test the functionality because we
> > can't be sure how many changes would be required for a timeout to
> > occur. This is just for brainstorming other options to test the
> > partial serialization functionality.
> >
>
> Apart from the above, we can also have a subscription option to
> specify parallel_shm_queue_size (queue_size used to determine the
> queue between the leader and parallel worker) and that can be used for
> this purpose. Basically, configuring it to a smaller value can help in
> reducing the test time but still, it will not eliminate the need for
> dependency on timing we have to wait before switching to partial
> serialize mode. I think this can be used in production as well to tune
> the performance depending on workload.
>
> Yet another way is to use the existing parameter logical_decode_mode
> [1]. If the value of logical_decoding_mode is 'immediate', then we can
> immediately switch to partial serialize mode. This will eliminate the
> dependency on timing. The one argument against using this is that it
> won't be as clear as a separate parameter like
> 'stream_serialize_threshold' proposed by the patch but OTOH we already
> have a few parameters that serve a different purpose when used on the
> subscriber. For example, 'max_replication_slots' is used to define the
> maximum number of replication slots on the publisher and the maximum
> number of origins on subscribers. Similarly,
> wal_retrieve_retry_interval' is used for different purposes on
> subscriber and standby nodes.
>
> [1] - https://www.postgresql.org/docs/devel/runtime-config-developer.html
>
> --
> With Regards,
> Amit Kapila.
Hi Amit,
On rethinking the complete model, what I feel is that the name
logical_decoding_mode is not something which defines modes of logical
decoding. We, I think, picked it based on logical_decoding_work_mem.
As per current implementation, the parameter 'logical_decoding_mode'
tells what happens when work-memory used by logical decoding reaches
its limit. So it is in-fact 'logicalrep_workmem_vacate_mode' or
'logicalrep_trans_eviction_mode'. So if it is set to immediate,
meaning vacate the work-memory immediately or evict transactions
immediately. Add buffered means the reverse (i.e. keep on buffering
transactions until we reach a limit). Now coming to subscribers, we
can reuse the same parameter. On subscriber as well, shared-memory
queue could be considered as its workmem and thus the name
'logicalrep_workmem_vacate_mode' might look more relevant.
On publisher:
logicalrep_workmem_vacate_mode=immediate, buffered.
On subscriber:
logicalrep_workmem_vacate_mode=stream_serialize (or if we want to
keep immediate here too, that will also be fine).
Thoughts?
And I am assuming it is possible to change the GUC name before the
coming release. If not, please let me know, we can brainstorm other
ideas.
thanks
Shveta
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 10:14 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
@ 2023-01-19 10:22 ` shveta malik <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: shveta malik @ 2023-01-19 10:22 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Peter Smith <[email protected]>; [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; shveta malik <[email protected]>
On Thu, Jan 19, 2023 at 3:44 PM shveta malik <[email protected]> wrote:
>
> On Thu, Jan 19, 2023 at 11:11 AM Amit Kapila <[email protected]> wrote:
> >
> > On Wed, Jan 18, 2023 at 12:09 PM Amit Kapila <[email protected]> wrote:
> > >
> > > On Fri, Jan 13, 2023 at 11:50 AM Peter Smith <[email protected]> wrote:
> > > >
> > > > Here are some review comments for patch v79-0002.
> > > >
> > >
> > > So, this is about the latest v84-0001-Stop-extra-worker-if-GUC-was-changed.
> > >
> > > >
> > > > I feel this patch just adds more complexity for almost no gain:
> > > > - reducing the 'max_apply_workers_per_suibscription' seems not very
> > > > common in the first place.
> > > > - even when the GUC is reduced, at that point in time all the workers
> > > > might be in use so there may be nothing that can be immediately done.
> > > > - IIUC the excess workers (for a reduced GUC) are going to get freed
> > > > naturally anyway over time as more transactions are completed so the
> > > > pool size will reduce accordingly.
> > > >
> > >
> > > I am still not sure if it is worth pursuing this patch because of the
> > > above reasons. I don't think it would be difficult to add this even at
> > > a later point in time if we really see a use case for this.
> > > Sawada-San, IIRC, you raised this point. What do you think?
> > >
> > > The other point I am wondering is whether we can have a different way
> > > to test partial serialization apart from introducing another developer
> > > GUC (stream_serialize_threshold). One possibility could be that we can
> > > have a subscription option (parallel_send_timeout or something like
> > > that) with some default value (current_timeout used in the patch)
> > > which will be used only when streaming = parallel. Users may want to
> > > wait for more time before serialization starts depending on the
> > > workload (say when resource usage is high on a subscriber-side
> > > machine, or there are concurrent long-running transactions that can
> > > block parallel apply for a bit longer time). I know with this as well
> > > it may not be straightforward to test the functionality because we
> > > can't be sure how many changes would be required for a timeout to
> > > occur. This is just for brainstorming other options to test the
> > > partial serialization functionality.
> > >
> >
> > Apart from the above, we can also have a subscription option to
> > specify parallel_shm_queue_size (queue_size used to determine the
> > queue between the leader and parallel worker) and that can be used for
> > this purpose. Basically, configuring it to a smaller value can help in
> > reducing the test time but still, it will not eliminate the need for
> > dependency on timing we have to wait before switching to partial
> > serialize mode. I think this can be used in production as well to tune
> > the performance depending on workload.
> >
> > Yet another way is to use the existing parameter logical_decode_mode
> > [1]. If the value of logical_decoding_mode is 'immediate', then we can
> > immediately switch to partial serialize mode. This will eliminate the
> > dependency on timing. The one argument against using this is that it
> > won't be as clear as a separate parameter like
> > 'stream_serialize_threshold' proposed by the patch but OTOH we already
> > have a few parameters that serve a different purpose when used on the
> > subscriber. For example, 'max_replication_slots' is used to define the
> > maximum number of replication slots on the publisher and the maximum
> > number of origins on subscribers. Similarly,
> > wal_retrieve_retry_interval' is used for different purposes on
> > subscriber and standby nodes.
> >
> > [1] - https://www.postgresql.org/docs/devel/runtime-config-developer.html
> >
> > --
> > With Regards,
> > Amit Kapila.
>
> Hi Amit,
>
> On rethinking the complete model, what I feel is that the name
> logical_decoding_mode is not something which defines modes of logical
> decoding. We, I think, picked it based on logical_decoding_work_mem.
> As per current implementation, the parameter 'logical_decoding_mode'
> tells what happens when work-memory used by logical decoding reaches
> its limit. So it is in-fact 'logicalrep_workmem_vacate_mode' or
Minor correction in what I said earlier:
As per current implementation, the parameter 'logical_decoding_mode'
more or less tells how to deal with workmem i.e. to keep it buffering
with txns until it reaches its limit or immediately vacate it.
> 'logicalrep_trans_eviction_mode'. So if it is set to immediate,
> meaning vacate the work-memory immediately or evict transactions
> immediately. Add buffered means the reverse (i.e. keep on buffering
> transactions until we reach a limit). Now coming to subscribers, we
> can reuse the same parameter. On subscriber as well, shared-memory
> queue could be considered as its workmem and thus the name
> 'logicalrep_workmem_vacate_mode' might look more relevant.
>
> On publisher:
> logicalrep_workmem_vacate_mode=immediate, buffered.
>
> On subscriber:
> logicalrep_workmem_vacate_mode=stream_serialize (or if we want to
> keep immediate here too, that will also be fine).
>
> Thoughts?
> And I am assuming it is possible to change the GUC name before the
> coming release. If not, please let me know, we can brainstorm other
> ideas.
>
> thanks
> Shveta
thanks
Shveta
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-20 06:17 ` Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
1 sibling, 1 reply; 105+ messages in thread
From: Masahiko Sawada @ 2023-01-20 06:17 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Peter Smith <[email protected]>; [email protected] <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Thu, Jan 19, 2023 at 2:41 PM Amit Kapila <[email protected]> wrote:
>
> On Wed, Jan 18, 2023 at 12:09 PM Amit Kapila <[email protected]> wrote:
> >
> > On Fri, Jan 13, 2023 at 11:50 AM Peter Smith <[email protected]> wrote:
> > >
> > > Here are some review comments for patch v79-0002.
> > >
> >
> > So, this is about the latest v84-0001-Stop-extra-worker-if-GUC-was-changed.
> >
> > >
> > > I feel this patch just adds more complexity for almost no gain:
> > > - reducing the 'max_apply_workers_per_suibscription' seems not very
> > > common in the first place.
> > > - even when the GUC is reduced, at that point in time all the workers
> > > might be in use so there may be nothing that can be immediately done.
> > > - IIUC the excess workers (for a reduced GUC) are going to get freed
> > > naturally anyway over time as more transactions are completed so the
> > > pool size will reduce accordingly.
> > >
> >
> > I am still not sure if it is worth pursuing this patch because of the
> > above reasons. I don't think it would be difficult to add this even at
> > a later point in time if we really see a use case for this.
> > Sawada-San, IIRC, you raised this point. What do you think?
> >
> > The other point I am wondering is whether we can have a different way
> > to test partial serialization apart from introducing another developer
> > GUC (stream_serialize_threshold). One possibility could be that we can
> > have a subscription option (parallel_send_timeout or something like
> > that) with some default value (current_timeout used in the patch)
> > which will be used only when streaming = parallel. Users may want to
> > wait for more time before serialization starts depending on the
> > workload (say when resource usage is high on a subscriber-side
> > machine, or there are concurrent long-running transactions that can
> > block parallel apply for a bit longer time). I know with this as well
> > it may not be straightforward to test the functionality because we
> > can't be sure how many changes would be required for a timeout to
> > occur. This is just for brainstorming other options to test the
> > partial serialization functionality.
I can see parallel_send_timeout idea could be useful somewhat but I'm
concerned users can tune this value properly. It's likely to indicate
something abnormal or locking issues if LA waits to write data to the
queue for more than 10s. Also, I think it doesn't make sense to allow
users to set this timeout to a very low value. If switching to partial
serialization mode early is useful in some cases, I think it's better
to provide it as a new mode, such as streaming = 'parallel-file' etc.
>
> Apart from the above, we can also have a subscription option to
> specify parallel_shm_queue_size (queue_size used to determine the
> queue between the leader and parallel worker) and that can be used for
> this purpose. Basically, configuring it to a smaller value can help in
> reducing the test time but still, it will not eliminate the need for
> dependency on timing we have to wait before switching to partial
> serialize mode. I think this can be used in production as well to tune
> the performance depending on workload.
A parameter for the queue size is interesting but I agree it will not
eliminate the need for dependency on timing.
>
> Yet another way is to use the existing parameter logical_decode_mode
> [1]. If the value of logical_decoding_mode is 'immediate', then we can
> immediately switch to partial serialize mode. This will eliminate the
> dependency on timing. The one argument against using this is that it
> won't be as clear as a separate parameter like
> 'stream_serialize_threshold' proposed by the patch but OTOH we already
> have a few parameters that serve a different purpose when used on the
> subscriber. For example, 'max_replication_slots' is used to define the
> maximum number of replication slots on the publisher and the maximum
> number of origins on subscribers. Similarly,
> wal_retrieve_retry_interval' is used for different purposes on
> subscriber and standby nodes.
Using the existing parameter makes sense to me. But if we use
logical_decoding_mode also on the subscriber, as Shveta Malik also
suggested, probably it's better to rename it so as not to confuse. For
example, logical_replication_mode or something.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-01-23 03:17 ` Amit Kapila <[email protected]>
2023-01-23 05:58 ` Re: Perform streaming logical transactions by background workers and parallel apply Dilip Kumar <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
0 siblings, 2 replies; 105+ messages in thread
From: Amit Kapila @ 2023-01-23 03:17 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: Peter Smith <[email protected]>; [email protected] <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Fri, Jan 20, 2023 at 11:48 AM Masahiko Sawada <[email protected]> wrote:
>
> >
> > Yet another way is to use the existing parameter logical_decode_mode
> > [1]. If the value of logical_decoding_mode is 'immediate', then we can
> > immediately switch to partial serialize mode. This will eliminate the
> > dependency on timing. The one argument against using this is that it
> > won't be as clear as a separate parameter like
> > 'stream_serialize_threshold' proposed by the patch but OTOH we already
> > have a few parameters that serve a different purpose when used on the
> > subscriber. For example, 'max_replication_slots' is used to define the
> > maximum number of replication slots on the publisher and the maximum
> > number of origins on subscribers. Similarly,
> > wal_retrieve_retry_interval' is used for different purposes on
> > subscriber and standby nodes.
>
> Using the existing parameter makes sense to me. But if we use
> logical_decoding_mode also on the subscriber, as Shveta Malik also
> suggested, probably it's better to rename it so as not to confuse. For
> example, logical_replication_mode or something.
>
+1. Among the options discussed, this sounds better.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-23 05:58 ` Dilip Kumar <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: Dilip Kumar @ 2023-01-23 05:58 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>
On Mon, Jan 23, 2023 at 8:47 AM Amit Kapila <[email protected]> wrote:
>
> On Fri, Jan 20, 2023 at 11:48 AM Masahiko Sawada <[email protected]> wrote:
> >
> > >
> > > Yet another way is to use the existing parameter logical_decode_mode
> > > [1]. If the value of logical_decoding_mode is 'immediate', then we can
> > > immediately switch to partial serialize mode. This will eliminate the
> > > dependency on timing. The one argument against using this is that it
> > > won't be as clear as a separate parameter like
> > > 'stream_serialize_threshold' proposed by the patch but OTOH we already
> > > have a few parameters that serve a different purpose when used on the
> > > subscriber. For example, 'max_replication_slots' is used to define the
> > > maximum number of replication slots on the publisher and the maximum
> > > number of origins on subscribers. Similarly,
> > > wal_retrieve_retry_interval' is used for different purposes on
> > > subscriber and standby nodes.
> >
> > Using the existing parameter makes sense to me. But if we use
> > logical_decoding_mode also on the subscriber, as Shveta Malik also
> > suggested, probably it's better to rename it so as not to confuse. For
> > example, logical_replication_mode or something.
> >
>
> +1. Among the options discussed, this sounds better.
Yeah, this looks better option with the parameter name
'logical_replication_mode'.
--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-23 08:05 ` [email protected] <[email protected]>
2023-01-23 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-24 03:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
1 sibling, 3 replies; 105+ messages in thread
From: [email protected] @ 2023-01-23 08:05 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Peter Smith <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Monday, January 23, 2023 11:17 AM Amit Kapila <[email protected]> wrote:
>
> On Fri, Jan 20, 2023 at 11:48 AM Masahiko Sawada <[email protected]>
> wrote:
> >
> > >
> > > Yet another way is to use the existing parameter logical_decode_mode
> > > [1]. If the value of logical_decoding_mode is 'immediate', then we
> > > can immediately switch to partial serialize mode. This will
> > > eliminate the dependency on timing. The one argument against using
> > > this is that it won't be as clear as a separate parameter like
> > > 'stream_serialize_threshold' proposed by the patch but OTOH we
> > > already have a few parameters that serve a different purpose when
> > > used on the subscriber. For example, 'max_replication_slots' is used
> > > to define the maximum number of replication slots on the publisher
> > > and the maximum number of origins on subscribers. Similarly,
> > > wal_retrieve_retry_interval' is used for different purposes on
> > > subscriber and standby nodes.
> >
> > Using the existing parameter makes sense to me. But if we use
> > logical_decoding_mode also on the subscriber, as Shveta Malik also
> > suggested, probably it's better to rename it so as not to confuse. For
> > example, logical_replication_mode or something.
> >
>
> +1. Among the options discussed, this sounds better.
OK, here is patch set which does the same.
The first patch set only renames the GUC name, and the second patch uses
the GUC to test the partial serialization.
Best Regards,
Hou zj
Attachments:
[application/octet-stream] v86-0002-Extend-the-logical_replication_mode-to-test-the-stre.patch (11.2K, ../../OS0PR01MB5716B68E724D9A321238483294C89@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v86-0002-Extend-the-logical_replication_mode-to-test-the-stre.patch)
download | inline diff:
From 5fe8f54ad16c3b8da0bf926293d7c4f1ce3fec8d Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 20 Jan 2023 16:59:37 +0800
Subject: [PATCH] Extend the logical_replication_mode to test the stream
parallel mode
Use the use the existing developer option logical_replication_mode to test the
parallel apply of large transaction on subscriber.
When set to 'buffered', the leader sends changes to parallel apply workers via
shared memory queue. When set to 'immediate', the leader serializes all changes
to files and notifies the parallel apply workers to read and apply them at the
end of the transaction.
---
doc/src/sgml/config.sgml | 12 ++++
.../replication/logical/applyparallelworker.c | 12 ++--
src/test/subscription/t/015_stream.pl | 27 ++++++++
.../t/018_stream_subxact_abort.pl | 65 ++++++++++++++++++-
.../subscription/t/023_twophase_stream.pl | 45 ++++++++++++-
5 files changed, 154 insertions(+), 7 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 275dcd55ba..87df627751 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11708,6 +11708,18 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
or serialize changes when <varname>logical_decoding_work_mem</varname>
is reached.
</para>
+
+ <para>
+ On the subscriber side, if <literal>streaming</literal> option is set
+ to <literal>parallel</literal>, this parameter also allows the leader
+ apply worker to send changes to the shared memory queue or to serialize
+ changes. When set to <literal>buffered</literal>, the leader sends
+ changes to parallel apply workers via shared memory queue. When set to
+ <literal>immediate</literal>, the leader serializes all changes to
+ files and notifies the parallel apply workers to read and apply them at
+ the end of the transaction.
+ </para>
+
<para>
This parameter is intended to be used to test logical decoding and
replication of large transactions for which otherwise we need to
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3579e704fe..39e8f2d36d 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -1149,6 +1149,9 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE)
+ return false;
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
@@ -1187,12 +1190,7 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
startTime = GetCurrentTimestamp();
else if (TimestampDifferenceExceeds(startTime, GetCurrentTimestamp(),
SHM_SEND_TIMEOUT_MS))
- {
- ereport(LOG,
- (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
- winfo->shared->xid)));
return false;
- }
}
}
@@ -1206,6 +1204,10 @@ void
pa_switch_to_partial_serialize(ParallelApplyWorkerInfo *winfo,
bool stream_locked)
{
+ ereport(LOG,
+ (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
+ winfo->shared->xid)));
+
/*
* The parallel apply worker could be stuck for some reason (say waiting
* on some lock by other backend), so stop trying to send data directly to
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8c0a..93086052f6 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -312,6 +312,33 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(15000), 'all changes are replayed from file');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index 814daf4d2f..1fa0ae0b05 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -143,15 +143,17 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c INT, d INT, e INT)");
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -198,6 +200,67 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK;
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0), 'all changes are replayed from file');
+
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'all changes are replayed from file');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 497245a209..e1bf63b97c 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -319,16 +319,18 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber (columns a and b are compatible with same table name on publisher)
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999)"
);
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication (streaming = on)
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -384,6 +386,47 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the messages are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'all changes are replayed from file');
+
###############################
# check all the cleanup
###############################
--
2.28.0.windows.1
[application/octet-stream] v86-0001-Rename-logical_decoding_mode-to-logical_replication_.patch (9.5K, ../../OS0PR01MB5716B68E724D9A321238483294C89@OS0PR01MB5716.jpnprd01.prod.outlook.com/3-v86-0001-Rename-logical_decoding_mode-to-logical_replication_.patch)
download | inline diff:
From b53dd94b2fb23f556a4bea8a2be4e1890e1db930 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 20 Jan 2023 14:39:38 +0800
Subject: [PATCH] Rename logical_decoding_mode to logical_replication_mode
Since we may extend the developer option logical_decoding_mode to to test the
parallel apply of large transaction on subscriber, rename this option to
logical_replication_mode to make it easier to understand.
---
doc/src/sgml/config.sgml | 8 ++++----
src/backend/replication/logical/reorderbuffer.c | 12 ++++++------
src/backend/utils/misc/guc_tables.c | 10 +++++-----
src/include/replication/reorderbuffer.h | 10 +++++-----
src/test/subscription/t/016_stream_subxact.pl | 2 +-
src/test/subscription/t/018_stream_subxact_abort.pl | 2 +-
src/test/subscription/t/019_stream_subxact_ddl_abort.pl | 2 +-
src/test/subscription/t/023_twophase_stream.pl | 2 +-
src/tools/pgindent/typedefs.list | 2 +-
9 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 77574e2..638c99d 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11655,16 +11655,16 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
- <varlistentry id="guc-logical-decoding-mode" xreflabel="logical_decoding_mode">
- <term><varname>logical_decoding_mode</varname> (<type>enum</type>)
+ <varlistentry id="guc-logical-replication-mode" xreflabel="logical_replication_mode">
+ <term><varname>logical_replication_mode</varname> (<type>enum</type>)
<indexterm>
- <primary><varname>logical_decoding_mode</varname> configuration parameter</primary>
+ <primary><varname>logical_replication_mode</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Allows streaming or serializing changes immediately in logical decoding.
- The allowed values of <varname>logical_decoding_mode</varname> are
+ The allowed values of <varname>logical_replication_mode</varname> are
<literal>buffered</literal> and <literal>immediate</literal>. When set
to <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 54ee824..42a137d 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -210,7 +210,7 @@ int logical_decoding_work_mem;
static const Size max_changes_in_memory = 4096; /* XXX for restore only */
/* GUC variable */
-int logical_decoding_mode = LOGICAL_DECODING_MODE_BUFFERED;
+int logical_replication_mode = LOGICAL_REP_MODE_BUFFERED;
/* ---------------------------------------
* primary reorderbuffer support routines
@@ -3552,7 +3552,7 @@ ReorderBufferLargestStreamableTopTXN(ReorderBuffer *rb)
* pick the largest (sub)transaction at-a-time to evict and spill its changes to
* disk or send to the output plugin until we reach under the memory limit.
*
- * If logical_decoding_mode is set to "immediate", stream or serialize the changes
+ * If logical_replication_mode is set to "immediate", stream or serialize the changes
* immediately.
*
* XXX At this point we select the transactions until we reach under the memory
@@ -3566,15 +3566,15 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
ReorderBufferTXN *txn;
/*
- * Bail out if logical_decoding_mode is buffered and we haven't exceeded
+ * Bail out if logical_replication_mode is buffered and we haven't exceeded
* the memory limit.
*/
- if (logical_decoding_mode == LOGICAL_DECODING_MODE_BUFFERED &&
+ if (logical_replication_mode == LOGICAL_REP_MODE_BUFFERED &&
rb->size < logical_decoding_work_mem * 1024L)
return;
/*
- * If logical_decoding_mode is immediate, loop until there's no change.
+ * If logical_replication_mode is immediate, loop until there's no change.
* Otherwise, loop until we reach under the memory limit. One might think
* that just by evicting the largest (sub)transaction we will come under
* the memory limit based on assumption that the selected transaction is
@@ -3584,7 +3584,7 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
* change.
*/
while (rb->size >= logical_decoding_work_mem * 1024L ||
- (logical_decoding_mode == LOGICAL_DECODING_MODE_IMMEDIATE &&
+ (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE &&
rb->size > 0))
{
/*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 5025e80..705920c 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -396,8 +396,8 @@ static const struct config_enum_entry ssl_protocol_versions_info[] = {
};
static const struct config_enum_entry logical_decoding_mode_options[] = {
- {"buffered", LOGICAL_DECODING_MODE_BUFFERED, false},
- {"immediate", LOGICAL_DECODING_MODE_IMMEDIATE, false},
+ {"buffered", LOGICAL_REP_MODE_BUFFERED, false},
+ {"immediate", LOGICAL_REP_MODE_IMMEDIATE, false},
{NULL, 0, false}
};
@@ -4908,13 +4908,13 @@ struct config_enum ConfigureNamesEnum[] =
},
{
- {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
+ {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
gettext_noop("Allows streaming or serializing each change in logical decoding."),
NULL,
GUC_NOT_IN_SAMPLE
},
- &logical_decoding_mode,
- LOGICAL_DECODING_MODE_BUFFERED, logical_decoding_mode_options,
+ &logical_replication_mode,
+ LOGICAL_REP_MODE_BUFFERED, logical_decoding_mode_options,
NULL, NULL, NULL
},
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index f6c4dd7..5a26ec9 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -18,14 +18,14 @@
#include "utils/timestamp.h"
extern PGDLLIMPORT int logical_decoding_work_mem;
-extern PGDLLIMPORT int logical_decoding_mode;
+extern PGDLLIMPORT int logical_replication_mode;
-/* possible values for logical_decoding_mode */
+/* possible values for logical_replication_mode */
typedef enum
{
- LOGICAL_DECODING_MODE_BUFFERED,
- LOGICAL_DECODING_MODE_IMMEDIATE
-} LogicalDecodingMode;
+ LOGICAL_REP_MODE_BUFFERED,
+ LOGICAL_REP_MODE_IMMEDIATE
+} LogicalRepMode;
/* an individual tuple, stored in one chunk of memory */
typedef struct ReorderBufferTupleBuf
diff --git a/src/test/subscription/t/016_stream_subxact.pl b/src/test/subscription/t/016_stream_subxact.pl
index 2f0148c..d830f26 100644
--- a/src/test/subscription/t/016_stream_subxact.pl
+++ b/src/test/subscription/t/016_stream_subxact.pl
@@ -79,7 +79,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index dce14b1..814daf4 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -130,7 +130,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
index b30223d..d0e556c 100644
--- a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
+++ b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
@@ -16,7 +16,7 @@ use Test::More;
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 75ca837..497245a 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -301,7 +301,7 @@ $node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf(
'postgresql.conf', qq(
max_prepared_transactions = 10
-logical_decoding_mode = immediate
+logical_replication_mode = immediate
));
$node_publisher->start;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 23bafec..d0d61d8 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1456,7 +1456,6 @@ LogicalDecodeStreamStopCB
LogicalDecodeStreamTruncateCB
LogicalDecodeTruncateCB
LogicalDecodingContext
-LogicalDecodingMode
LogicalErrorCallbackState
LogicalOutputPluginInit
LogicalOutputPluginWriterPrepareWrite
@@ -1466,6 +1465,7 @@ LogicalRepBeginData
LogicalRepCommitData
LogicalRepCommitPreparedTxnData
LogicalRepCtxStruct
+LogicalRepMode
LogicalRepMsgType
LogicalRepPartMapEntry
LogicalRepPreparedTxnData
--
2.7.2.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-23 12:34 ` Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Hayato Kuroda (Fujitsu) @ 2023-01-23 12:34 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Peter Smith <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Amit Kapila <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
Dear Hou,
Thank you for updating the patch! Followings are my comments.
1. guc_tables.c
```
static const struct config_enum_entry logical_decoding_mode_options[] = {
- {"buffered", LOGICAL_DECODING_MODE_BUFFERED, false},
- {"immediate", LOGICAL_DECODING_MODE_IMMEDIATE, false},
+ {"buffered", LOGICAL_REP_MODE_BUFFERED, false},
+ {"immediate", LOGICAL_REP_MODE_IMMEDIATE, false},
{NULL, 0, false}
};
```
This struct should be also modified.
2. guc_tables.c
```
- {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
+ {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
gettext_noop("Allows streaming or serializing each change in logical decoding."),
NULL,
```
I felt the description seems not to be suitable for current behavior.
A short description should be like "Sets a behavior of logical replication", and
further descriptions can be added in lond description.
3. config.sgml
```
<para>
This parameter is intended to be used to test logical decoding and
replication of large transactions for which otherwise we need to
generate the changes till <varname>logical_decoding_work_mem</varname>
is reached.
</para>
```
I understood that this part described the usage of the parameter. How about adding
a statement like:
" Moreover, this can be also used to test the message passing between the leader
and parallel apply workers."
4. 015_stream.pl
```
+# Ensure that the messages are serialized.
```
In other parts "changes" are used instead of "messages". Can you change the word?
Best Regards,
Hayato Kuroda
FUJITSU LIMITED
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-23 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
@ 2023-01-24 12:47 ` [email protected] <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: [email protected] @ 2023-01-24 12:47 UTC (permalink / raw)
To: Hayato Kuroda (Fujitsu) <[email protected]>; +Cc: Peter Smith <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Amit Kapila <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Monday, January 23, 2023 8:34 PM Kuroda, Hayato wrote:
>
> Followings are my comments.
Thanks for your comments.
>
> 1. guc_tables.c
>
> ```
> static const struct config_enum_entry logical_decoding_mode_options[] = {
> - {"buffered", LOGICAL_DECODING_MODE_BUFFERED, false},
> - {"immediate", LOGICAL_DECODING_MODE_IMMEDIATE, false},
> + {"buffered", LOGICAL_REP_MODE_BUFFERED, false},
> + {"immediate", LOGICAL_REP_MODE_IMMEDIATE, false},
> {NULL, 0, false}
> };
> ```
>
> This struct should be also modified.
Modified.
>
> 2. guc_tables.c
>
>
> ```
> - {"logical_decoding_mode", PGC_USERSET,
> DEVELOPER_OPTIONS,
> + {"logical_replication_mode", PGC_USERSET,
> + DEVELOPER_OPTIONS,
> gettext_noop("Allows streaming or serializing each
> change in logical decoding."),
> NULL,
> ```
>
> I felt the description seems not to be suitable for current behavior.
> A short description should be like "Sets a behavior of logical replication", and
> further descriptions can be added in lond description.
I adjusted the description here.
> 3. config.sgml
>
> ```
> <para>
> This parameter is intended to be used to test logical decoding and
> replication of large transactions for which otherwise we need to
> generate the changes till
> <varname>logical_decoding_work_mem</varname>
> is reached.
> </para>
> ```
>
> I understood that this part described the usage of the parameter. How about
> adding a statement like:
>
> " Moreover, this can be also used to test the message passing between the
> leader and parallel apply workers."
Added.
> 4. 015_stream.pl
>
> ```
> +# Ensure that the messages are serialized.
> ```
>
> In other parts "changes" are used instead of "messages". Can you change the
> word?
Changed.
Best Regards,
Hou zj
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-24 03:43 ` Peter Smith <[email protected]>
2023-01-24 04:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2 siblings, 2 replies; 105+ messages in thread
From: Peter Smith @ 2023-01-24 03:43 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
Here are my review comments for patch v86-0001.
======
General
1.
IIUC the GUC name was made generic 'logical_replication_mode' so that
multiple developer GUCs are not needed later.
But IMO those current option values (buffered/immediate) for that GUC
are maybe a bit too generic. Perhaps in future, we might want more
granular control than that allows. e.g. I can imagine there might be
multiple different meanings for what "buffered" means. If there is any
chance of the generic values being problematic later then maybe they
should be made more specific up-front.
e.g. maybe like:
logical_replication_mode = buffered_decoding
logical_replication_mode = immediate_decoding
Thoughts?
======
Commit message
2.
Since we may extend the developer option logical_decoding_mode to to test the
parallel apply of large transaction on subscriber, rename this option to
logical_replication_mode to make it easier to understand.
~
2a
typo "to to"
typo "large transaction on subscriber" --> "large transactions on the
subscriber"
~
2b.
IMO better to rephrase the whole paragraph like shown below.
SUGGESTION
Rename the developer option 'logical_decoding_mode' to the more
flexible name 'logical_replication_mode' because doing so will make it
easier to extend this option in future to help test other areas of
logical replication.
======
doc/src/sgml/config.sgml
3.
Allows streaming or serializing changes immediately in logical
decoding. The allowed values of logical_replication_mode are buffered
and immediate. When set to immediate, stream each change if streaming
option (see optional parameters set by CREATE SUBSCRIPTION) is
enabled, otherwise, serialize each change. When set to buffered, which
is the default, decoding will stream or serialize changes when
logical_decoding_work_mem is reached.
~
IMO it's more clear to say the default when the options are first
mentioned. So I suggested removing the "which is the default" part,
and instead saying:
BEFORE
The allowed values of logical_replication_mode are buffered and immediate.
AFTER
The allowed values of logical_replication_mode are buffered and
immediate. The default is buffered.
======
src/backend/utils/misc/guc_tables.c
4.
@@ -396,8 +396,8 @@ static const struct config_enum_entry
ssl_protocol_versions_info[] = {
};
static const struct config_enum_entry logical_decoding_mode_options[] = {
- {"buffered", LOGICAL_DECODING_MODE_BUFFERED, false},
- {"immediate", LOGICAL_DECODING_MODE_IMMEDIATE, false},
+ {"buffered", LOGICAL_REP_MODE_BUFFERED, false},
+ {"immediate", LOGICAL_REP_MODE_IMMEDIATE, false},
{NULL, 0, false}
};
I noticed this array is still called "logical_decoding_mode_options".
Was that deliberate?
------
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 03:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-24 04:42 ` Amit Kapila <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: Amit Kapila @ 2023-01-24 04:42 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Tue, Jan 24, 2023 at 9:13 AM Peter Smith <[email protected]> wrote:
>
> 1.
>
> IIUC the GUC name was made generic 'logical_replication_mode' so that
> multiple developer GUCs are not needed later.
>
> But IMO those current option values (buffered/immediate) for that GUC
> are maybe a bit too generic. Perhaps in future, we might want more
> granular control than that allows. e.g. I can imagine there might be
> multiple different meanings for what "buffered" means. If there is any
> chance of the generic values being problematic later then maybe they
> should be made more specific up-front.
>
> e.g. maybe like:
> logical_replication_mode = buffered_decoding
> logical_replication_mode = immediate_decoding
>
For now, it seems the meaning of buffered/immediate suits our
debugging and test needs for publisher/subscriber. This is somewhat
explained in Shveta's email [1]. I also think in the future this
parameter could be extended for a different purpose but maybe it would
be better to invent some new values at that time as things would be
more clear. We could do what you are suggesting or in fact even use
different values for publisher and subscriber but not really sure
whether that will simplify the usage.
[1] - https://www.postgresql.org/message-id/CAJpy0uDzddK_ZUsB2qBJUbW_ZODYGoUHTaS5pVcYE2tzATCVXQ%40mail.gma...
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 03:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-24 12:47 ` [email protected] <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: [email protected] @ 2023-01-24 12:47 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Tuesday, January 24, 2023 11:43 AM Peter Smith <[email protected]> wrote:
>
> Here are my review comments for patch v86-0001.
Thanks for your comments.
>
>
> ======
> Commit message
>
> 2.
> Since we may extend the developer option logical_decoding_mode to to test the
> parallel apply of large transaction on subscriber, rename this option to
> logical_replication_mode to make it easier to understand.
>
> ~
>
> 2a
> typo "to to"
>
> typo "large transaction on subscriber" --> "large transactions on the subscriber"
>
> ~
>
> 2b.
> IMO better to rephrase the whole paragraph like shown below.
>
> SUGGESTION
>
> Rename the developer option 'logical_decoding_mode' to the more flexible
> name 'logical_replication_mode' because doing so will make it easier to extend
> this option in future to help test other areas of logical replication.
Changed.
> ======
> doc/src/sgml/config.sgml
>
> 3.
> Allows streaming or serializing changes immediately in logical decoding. The
> allowed values of logical_replication_mode are buffered and immediate. When
> set to immediate, stream each change if streaming option (see optional
> parameters set by CREATE SUBSCRIPTION) is enabled, otherwise, serialize each
> change. When set to buffered, which is the default, decoding will stream or
> serialize changes when logical_decoding_work_mem is reached.
>
> ~
>
> IMO it's more clear to say the default when the options are first mentioned. So I
> suggested removing the "which is the default" part, and instead saying:
>
> BEFORE
> The allowed values of logical_replication_mode are buffered and immediate.
>
> AFTER
> The allowed values of logical_replication_mode are buffered and immediate. The
> default is buffered.
I included this change in the 0002 patch.
> ======
> src/backend/utils/misc/guc_tables.c
>
> 4.
> @@ -396,8 +396,8 @@ static const struct config_enum_entry
> ssl_protocol_versions_info[] = { };
>
> static const struct config_enum_entry logical_decoding_mode_options[] = {
> - {"buffered", LOGICAL_DECODING_MODE_BUFFERED, false},
> - {"immediate", LOGICAL_DECODING_MODE_IMMEDIATE, false},
> + {"buffered", LOGICAL_REP_MODE_BUFFERED, false}, {"immediate",
> + LOGICAL_REP_MODE_IMMEDIATE, false},
> {NULL, 0, false}
> };
>
> I noticed this array is still called "logical_decoding_mode_options".
> Was that deliberate?
No, I didn't notice this one. Changed.
Best Regards,
Hou zj
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-24 07:18 ` Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Peter Smith @ 2023-01-24 07:18 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
Here are some review comments for v86-0002
======
Commit message
1.
Use the use the existing developer option logical_replication_mode to test the
parallel apply of large transaction on subscriber.
~
Typo “Use the use the”
SUGGESTION (rewritten)
Give additional functionality to the existing developer option
'logical_replication_mode' to help test parallel apply of large
transactions on the subscriber.
~~~
2.
Maybe that commit message should also say extra TAP tests that have
been added to exercise the serialization part of the parallel apply?
BTW – I can see the TAP tests are testing full serialization (when the
GUC is 'immediate') but I not sure how is "partial" serialization
(when it has to switch halfway from shmem to files) being tested.
======
doc/src/sgml/config.sgml
3.
Allows streaming or serializing changes immediately in logical
decoding. The allowed values of logical_replication_mode are buffered
and immediate. When set to immediate, stream each change if streaming
option (see optional parameters set by CREATE SUBSCRIPTION) is
enabled, otherwise, serialize each change. When set to buffered, which
is the default, decoding will stream or serialize changes when
logical_decoding_work_mem is reached.
On the subscriber side, if streaming option is set to parallel, this
parameter also allows the leader apply worker to send changes to the
shared memory queue or to serialize changes. When set to buffered, the
leader sends changes to parallel apply workers via shared memory
queue. When set to immediate, the leader serializes all changes to
files and notifies the parallel apply workers to read and apply them
at the end of the transaction.
~
Because now this same developer GUC affects both the publisher side
and the subscriber side differently IMO this whole description should
be re-structured accordingly.
SUGGESTION (something like)
The allowed values of logical_replication_mode are buffered and
immediate. The default is buffered.
On the publisher side, ...
On the subscriber side, ...
~~~
4.
This parameter is intended to be used to test logical decoding and
replication of large transactions for which otherwise we need to
generate the changes till logical_decoding_work_mem is reached.
~
Maybe this paragraph needs rewording or moving. e.g. Isn't that
misleading now? Although this might be an explanation for the
publisher side, it does not seem relevant to the subscriber side's
behaviour.
======
.../replication/logical/applyparallelworker.c
5.
@ -1149,6 +1149,9 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size
nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE)
+ return false;
+
I felt that code should have some comment, even if it is just
something quite basic like "/* For developer testing */"
======
.../t/018_stream_subxact_abort.pl
6.
+# Clean up test data from the environment.
+$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
+$node_publisher->wait_for_catchup($appname);
Is it necessary to TRUNCATE the table here? If everything is working
shouldn't the data be rolled back anyway?
~~~
7.
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
Perhaps this should insert 2 different values so then the verification
code can check the correct value remains instead of just checking
COUNT(*)?
------
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-24 12:47 ` [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: [email protected] @ 2023-01-24 12:47 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Tuesday, January 24, 2023 3:19 PM Peter Smith <[email protected]> wrote:
>
> Here are some review comments for v86-0002
>
> ======
> Commit message
>
> 1.
> Use the use the existing developer option logical_replication_mode to test the
> parallel apply of large transaction on subscriber.
>
> ~
>
> Typo “Use the use the”
>
> SUGGESTION (rewritten)
> Give additional functionality to the existing developer option
> 'logical_replication_mode' to help test parallel apply of large transactions on the
> subscriber.
Changed.
> ~~~
>
> 2.
> Maybe that commit message should also say extra TAP tests that have been
> added to exercise the serialization part of the parallel apply?
Added.
> BTW – I can see the TAP tests are testing full serialization (when the GUC is
> 'immediate') but I not sure how is "partial" serialization (when it has to switch
> halfway from shmem to files) being tested.
The new tests are intended to test most of new code patch for partial
serialization by doing it from the beginning. Later, if required, we can add
different tests for it.
>
> ======
> doc/src/sgml/config.sgml
>
> 3.
> Allows streaming or serializing changes immediately in logical decoding. The
> allowed values of logical_replication_mode are buffered and immediate. When
> set to immediate, stream each change if streaming option (see optional
> parameters set by CREATE SUBSCRIPTION) is enabled, otherwise, serialize each
> change. When set to buffered, which is the default, decoding will stream or
> serialize changes when logical_decoding_work_mem is reached.
> On the subscriber side, if streaming option is set to parallel, this parameter also
> allows the leader apply worker to send changes to the shared memory queue or
> to serialize changes. When set to buffered, the leader sends changes to parallel
> apply workers via shared memory queue. When set to immediate, the leader
> serializes all changes to files and notifies the parallel apply workers to read and
> apply them at the end of the transaction.
>
> ~
>
> Because now this same developer GUC affects both the publisher side and the
> subscriber side differently IMO this whole description should be re-structured
> accordingly.
>
> SUGGESTION (something like)
>
> The allowed values of logical_replication_mode are buffered and immediate. The
> default is buffered.
>
> On the publisher side, ...
>
> On the subscriber side, ...
Changed.
>
> ~~~
>
> 4.
> This parameter is intended to be used to test logical decoding and replication of
> large transactions for which otherwise we need to generate the changes till
> logical_decoding_work_mem is reached.
>
> ~
>
> Maybe this paragraph needs rewording or moving. e.g. Isn't that misleading
> now? Although this might be an explanation for the publisher side, it does not
> seem relevant to the subscriber side's behaviour.
Adjusted the description here.
>
> ======
> .../replication/logical/applyparallelworker.c
>
> 5.
> @ -1149,6 +1149,9 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size
> nbytes, const void *data)
> Assert(!IsTransactionState());
> Assert(!winfo->serialize_changes);
>
> + if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE) return
> + false;
> +
>
> I felt that code should have some comment, even if it is just something quite
> basic like "/* For developer testing */"
Added.
>
> ======
> .../t/018_stream_subxact_abort.pl
>
> 6.
> +# Clean up test data from the environment.
> +$node_publisher->safe_psql('postgres', "TRUNCATE TABLE test_tab_2");
> +$node_publisher->wait_for_catchup($appname);
>
> Is it necessary to TRUNCATE the table here? If everything is working shouldn't
> the data be rolled back anyway?
I think it's unnecessary, so removed.
>
> ~~~
>
> 7.
> +$node_publisher->safe_psql(
> + 'postgres', q{
> + BEGIN;
> + INSERT INTO test_tab_2 values(1);
> + SAVEPOINT sp;
> + INSERT INTO test_tab_2 values(1);
> + ROLLBACK TO sp;
> + COMMIT;
> + });
>
> Perhaps this should insert 2 different values so then the verification code can
> check the correct value remains instead of just checking COUNT(*)?
I think testing the count should be ok as the nearby testcases are
also checking the count.
Best regards,
Hou zj
Attachments:
[application/octet-stream] v87-0001-Rename-logical_decoding_mode-to-logical_replicat.patch (9.7K, ../../OS0PR01MB57167F14EED6B95582155D9194C99@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v87-0001-Rename-logical_decoding_mode-to-logical_replicat.patch)
download | inline diff:
From 069f60eccc75249ef31a856fca49ff2be628d736 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 20 Jan 2023 14:39:38 +0800
Subject: [PATCH v87] Rename logical_decoding_mode to logical_replication_mode
Rename the developer option 'logical_decoding_mode' to the more
flexible name 'logical_replication_mode' because doing so will make it
easier to extend this option in future to help test other areas of
logical replication.
---
doc/src/sgml/config.sgml | 8 ++++----
src/backend/replication/logical/reorderbuffer.c | 14 +++++++-------
src/backend/utils/misc/guc_tables.c | 12 ++++++------
src/include/replication/reorderbuffer.h | 10 +++++-----
src/test/subscription/t/016_stream_subxact.pl | 2 +-
.../subscription/t/018_stream_subxact_abort.pl | 2 +-
.../subscription/t/019_stream_subxact_ddl_abort.pl | 2 +-
src/test/subscription/t/023_twophase_stream.pl | 2 +-
src/tools/pgindent/typedefs.list | 2 +-
9 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index f985afc009..1cf53c74ea 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11693,16 +11693,16 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
- <varlistentry id="guc-logical-decoding-mode" xreflabel="logical_decoding_mode">
- <term><varname>logical_decoding_mode</varname> (<type>enum</type>)
+ <varlistentry id="guc-logical-replication-mode" xreflabel="logical_replication_mode">
+ <term><varname>logical_replication_mode</varname> (<type>enum</type>)
<indexterm>
- <primary><varname>logical_decoding_mode</varname> configuration parameter</primary>
+ <primary><varname>logical_replication_mode</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Allows streaming or serializing changes immediately in logical decoding.
- The allowed values of <varname>logical_decoding_mode</varname> are
+ The allowed values of <varname>logical_replication_mode</varname> are
<literal>buffered</literal> and <literal>immediate</literal>. When set
to <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 54ee824e6c..efe057b4de 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -210,7 +210,7 @@ int logical_decoding_work_mem;
static const Size max_changes_in_memory = 4096; /* XXX for restore only */
/* GUC variable */
-int logical_decoding_mode = LOGICAL_DECODING_MODE_BUFFERED;
+int logical_replication_mode = LOGICAL_REP_MODE_BUFFERED;
/* ---------------------------------------
* primary reorderbuffer support routines
@@ -3552,8 +3552,8 @@ ReorderBufferLargestStreamableTopTXN(ReorderBuffer *rb)
* pick the largest (sub)transaction at-a-time to evict and spill its changes to
* disk or send to the output plugin until we reach under the memory limit.
*
- * If logical_decoding_mode is set to "immediate", stream or serialize the changes
- * immediately.
+ * If logical_replication_mode is set to "immediate", stream or serialize the
+ * changes immediately.
*
* XXX At this point we select the transactions until we reach under the memory
* limit, but we might also adapt a more elaborate eviction strategy - for example
@@ -3566,15 +3566,15 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
ReorderBufferTXN *txn;
/*
- * Bail out if logical_decoding_mode is buffered and we haven't exceeded
+ * Bail out if logical_replication_mode is buffered and we haven't exceeded
* the memory limit.
*/
- if (logical_decoding_mode == LOGICAL_DECODING_MODE_BUFFERED &&
+ if (logical_replication_mode == LOGICAL_REP_MODE_BUFFERED &&
rb->size < logical_decoding_work_mem * 1024L)
return;
/*
- * If logical_decoding_mode is immediate, loop until there's no change.
+ * If logical_replication_mode is immediate, loop until there's no change.
* Otherwise, loop until we reach under the memory limit. One might think
* that just by evicting the largest (sub)transaction we will come under
* the memory limit based on assumption that the selected transaction is
@@ -3584,7 +3584,7 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
* change.
*/
while (rb->size >= logical_decoding_work_mem * 1024L ||
- (logical_decoding_mode == LOGICAL_DECODING_MODE_IMMEDIATE &&
+ (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE &&
rb->size > 0))
{
/*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 4ac808ed22..82ad425a9d 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -395,9 +395,9 @@ static const struct config_enum_entry ssl_protocol_versions_info[] = {
{NULL, 0, false}
};
-static const struct config_enum_entry logical_decoding_mode_options[] = {
- {"buffered", LOGICAL_DECODING_MODE_BUFFERED, false},
- {"immediate", LOGICAL_DECODING_MODE_IMMEDIATE, false},
+static const struct config_enum_entry logical_replication_mode_options[] = {
+ {"buffered", LOGICAL_REP_MODE_BUFFERED, false},
+ {"immediate", LOGICAL_REP_MODE_IMMEDIATE, false},
{NULL, 0, false}
};
@@ -4919,13 +4919,13 @@ struct config_enum ConfigureNamesEnum[] =
},
{
- {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
+ {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
gettext_noop("Allows streaming or serializing each change in logical decoding."),
NULL,
GUC_NOT_IN_SAMPLE
},
- &logical_decoding_mode,
- LOGICAL_DECODING_MODE_BUFFERED, logical_decoding_mode_options,
+ &logical_replication_mode,
+ LOGICAL_REP_MODE_BUFFERED, logical_replication_mode_options,
NULL, NULL, NULL
},
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index f6c4dd75db..5a26ec9187 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -18,14 +18,14 @@
#include "utils/timestamp.h"
extern PGDLLIMPORT int logical_decoding_work_mem;
-extern PGDLLIMPORT int logical_decoding_mode;
+extern PGDLLIMPORT int logical_replication_mode;
-/* possible values for logical_decoding_mode */
+/* possible values for logical_replication_mode */
typedef enum
{
- LOGICAL_DECODING_MODE_BUFFERED,
- LOGICAL_DECODING_MODE_IMMEDIATE
-} LogicalDecodingMode;
+ LOGICAL_REP_MODE_BUFFERED,
+ LOGICAL_REP_MODE_IMMEDIATE
+} LogicalRepMode;
/* an individual tuple, stored in one chunk of memory */
typedef struct ReorderBufferTupleBuf
diff --git a/src/test/subscription/t/016_stream_subxact.pl b/src/test/subscription/t/016_stream_subxact.pl
index 2f0148c3a8..d830f26e06 100644
--- a/src/test/subscription/t/016_stream_subxact.pl
+++ b/src/test/subscription/t/016_stream_subxact.pl
@@ -79,7 +79,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index dce14b150a..814daf4d2f 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -130,7 +130,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
index b30223de51..d0e556c8b8 100644
--- a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
+++ b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
@@ -16,7 +16,7 @@ use Test::More;
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 75ca83765e..497245a209 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -301,7 +301,7 @@ $node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf(
'postgresql.conf', qq(
max_prepared_transactions = 10
-logical_decoding_mode = immediate
+logical_replication_mode = immediate
));
$node_publisher->start;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 51484ca7e2..07fbb7ccf6 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1458,7 +1458,6 @@ LogicalDecodeStreamStopCB
LogicalDecodeStreamTruncateCB
LogicalDecodeTruncateCB
LogicalDecodingContext
-LogicalDecodingMode
LogicalErrorCallbackState
LogicalOutputPluginInit
LogicalOutputPluginWriterPrepareWrite
@@ -1468,6 +1467,7 @@ LogicalRepBeginData
LogicalRepCommitData
LogicalRepCommitPreparedTxnData
LogicalRepCtxStruct
+LogicalRepMode
LogicalRepMsgType
LogicalRepPartMapEntry
LogicalRepPreparedTxnData
--
2.28.0.windows.1
[application/octet-stream] v87-0002-Extend-the-logical_replication_mode-to-test-the-.patch (13.8K, ../../OS0PR01MB57167F14EED6B95582155D9194C99@OS0PR01MB5716.jpnprd01.prod.outlook.com/3-v87-0002-Extend-the-logical_replication_mode-to-test-the-.patch)
download | inline diff:
From 97399b94aa5dc19c722f999da1b7143a4a4ac41e Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 20 Jan 2023 16:59:37 +0800
Subject: [PATCH v87 2/2] Extend the logical_replication_mode to test the
stream parallel mode
Give additional functionality to the existing developer option
'logical_replication_mode' to help test parallel apply of large
transactions on the subscriber.
When set to 'buffered', the leader sends changes to parallel apply workers via
shared memory queue. When set to 'immediate', the leader serializes all changes
to files and notifies the parallel apply workers to read and apply them at the
end of the transaction.
This helps in adding tests to cover the serialization code path in parallel
streaming mode.
---
doc/src/sgml/config.sgml | 28 +++++++--
.../replication/logical/applyparallelworker.c | 16 +++--
src/backend/utils/misc/guc_tables.c | 10 ++-
src/test/subscription/t/015_stream.pl | 27 ++++++++
.../t/018_stream_subxact_abort.pl | 61 ++++++++++++++++++-
.../subscription/t/023_twophase_stream.pl | 45 +++++++++++++-
6 files changed, 173 insertions(+), 14 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 1cf53c74ea..f4d7cee611 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11701,10 +11701,15 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</term>
<listitem>
<para>
- Allows streaming or serializing changes immediately in logical decoding.
- The allowed values of <varname>logical_replication_mode</varname> are
- <literal>buffered</literal> and <literal>immediate</literal>. When set
- to <literal>immediate</literal>, stream each change if
+ The allowed values of logical_replication_mode are
+ <literal>buffered</literal> and <literal>immediate</literal>. The default
+ is <literal>buffered</literal>.
+ </para>
+
+ <para>
+ On the publisher side, it allows streaming or serializing changes
+ immediately in logical decoding. When set to
+ <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
<link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link>)
is enabled, otherwise, serialize each change. When set to
@@ -11712,11 +11717,24 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
or serialize changes when <varname>logical_decoding_work_mem</varname>
is reached.
</para>
+
+ <para>
+ On the subscriber side, if <literal>streaming</literal> option is set
+ to <literal>parallel</literal>, this parameter also allows the leader
+ apply worker to send changes to the shared memory queue or to serialize
+ changes. When set to <literal>buffered</literal>, the leader sends
+ changes to parallel apply workers via shared memory queue. When set to
+ <literal>immediate</literal>, the leader serializes all changes to
+ files and notifies the parallel apply workers to read and apply them at
+ the end of the transaction.
+ </para>
+
<para>
This parameter is intended to be used to test logical decoding and
replication of large transactions for which otherwise we need to
generate the changes till <varname>logical_decoding_work_mem</varname>
- is reached.
+ is reached. Moreover, this can also be used to test the transmission of
+ changes between the leader and parallel apply workers.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3579e704fe..17a8fd35cb 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -1149,6 +1149,13 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ /*
+ * In immeidate mode, directly return false so that we can switch to
+ * PARTIAL_SERIALIZE mode and serialize remaining changes to files.
+ */
+ if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE)
+ return false;
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
@@ -1187,12 +1194,7 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
startTime = GetCurrentTimestamp();
else if (TimestampDifferenceExceeds(startTime, GetCurrentTimestamp(),
SHM_SEND_TIMEOUT_MS))
- {
- ereport(LOG,
- (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
- winfo->shared->xid)));
return false;
- }
}
}
@@ -1206,6 +1208,10 @@ void
pa_switch_to_partial_serialize(ParallelApplyWorkerInfo *winfo,
bool stream_locked)
{
+ ereport(LOG,
+ (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
+ winfo->shared->xid)));
+
/*
* The parallel apply worker could be stuck for some reason (say waiting
* on some lock by other backend), so stop trying to send data directly to
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 82ad425a9d..e26780e8e9 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -4920,8 +4920,14 @@ struct config_enum ConfigureNamesEnum[] =
{
{"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Allows streaming or serializing each change in logical decoding."),
- NULL,
+ gettext_noop("Controls the behavior of logical replication publisher and subscriber"),
+ gettext_noop("If set to immediate, on the publisher side, it "
+ "allows streaming or serializing each change in "
+ "logical decoding. On the subscriber side, in "
+ "parallel streaming mode, it allows the leader apply "
+ "worker to serialize changes to files and notifies "
+ "the parallel apply workers to read and apply them at "
+ "the end of the transaction."),
GUC_NOT_IN_SAMPLE
},
&logical_replication_mode,
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8c0a..c591cfea5a 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -312,6 +312,33 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(15000), 'all changes are replayed from file');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index 814daf4d2f..5e87b462e6 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -143,15 +143,17 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c INT, d INT, e INT)");
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -198,6 +200,63 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0), 'check rollback was reflected on subscriber');
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'check rollback to savepoint was reflected on subscriber');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 497245a209..93ff5aa9d1 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -319,16 +319,18 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber (columns a and b are compatible with same table name on publisher)
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999)"
);
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication (streaming = on)
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -384,6 +386,47 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'transaction is committed on subscriber');
+
###############################
# check all the cleanup
###############################
--
2.28.0.windows.1
[application/octet-stream] v87-0002-Extend-the-logical_replication_mode-to-test-the-.patch (13.9K, ../../OS0PR01MB57167F14EED6B95582155D9194C99@OS0PR01MB5716.jpnprd01.prod.outlook.com/4-v87-0002-Extend-the-logical_replication_mode-to-test-the-.patch)
download | inline diff:
From f6b35de201dd4f094b78c83da044dc9f077cbd28 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 20 Jan 2023 16:59:37 +0800
Subject: [PATCH v87 2/2] Extend the logical_replication_mode to test the
stream parallel mode
Give additional functionality to the existing developer option
'logical_replication_mode' to help test parallel apply of large
transactions on the subscriber.
When set to 'buffered', the leader sends changes to parallel apply workers via
shared memory queue. When set to 'immediate', the leader serializes all changes
to files and notifies the parallel apply workers to read and apply them at the
end of the transaction.
This helps in adding tests to cover the serialization code path in parallel
streaming mode.
---
doc/src/sgml/config.sgml | 31 ++++++++---
.../replication/logical/applyparallelworker.c | 16 ++++--
src/backend/utils/misc/guc_tables.c | 10 +++-
src/test/subscription/t/015_stream.pl | 27 ++++++++++
.../subscription/t/018_stream_subxact_abort.pl | 61 +++++++++++++++++++++-
src/test/subscription/t/023_twophase_stream.pl | 45 +++++++++++++++-
6 files changed, 174 insertions(+), 16 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index c2c5877..5cdc3e9 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11663,22 +11663,39 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</term>
<listitem>
<para>
- Allows streaming or serializing changes immediately in logical decoding.
The allowed values of <varname>logical_replication_mode</varname> are
- <literal>buffered</literal> and <literal>immediate</literal>. When set
- to <literal>immediate</literal>, stream each change if
+ <literal>buffered</literal> and <literal>immediate</literal>. The default
+ is <literal>buffered</literal>.
+ </para>
+
+ <para>
+ On the publisher side, it allows streaming or serializing changes
+ immediately in logical decoding. When set to
+ <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
<link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link>)
is enabled, otherwise, serialize each change. When set to
- <literal>buffered</literal>, which is the default, decoding will stream
- or serialize changes when <varname>logical_decoding_work_mem</varname>
- is reached.
+ <literal>buffered</literal>, decoding will stream or serialize changes
+ when <varname>logical_decoding_work_mem</varname> is reached.
</para>
+
+ <para>
+ On the subscriber side, if <literal>streaming</literal> option is set
+ to <literal>parallel</literal>, this parameter also allows the leader
+ apply worker to send changes to the shared memory queue or to serialize
+ changes. When set to <literal>buffered</literal>, the leader sends
+ changes to parallel apply workers via shared memory queue. When set to
+ <literal>immediate</literal>, the leader serializes all changes to
+ files and notifies the parallel apply workers to read and apply them at
+ the end of the transaction.
+ </para>
+
<para>
This parameter is intended to be used to test logical decoding and
replication of large transactions for which otherwise we need to
generate the changes till <varname>logical_decoding_work_mem</varname>
- is reached.
+ is reached. Moreover, this can also be used to test the transmission of
+ changes between the leader and parallel apply workers.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3579e70..17a8fd3 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -1149,6 +1149,13 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ /*
+ * In immeidate mode, directly return false so that we can switch to
+ * PARTIAL_SERIALIZE mode and serialize remaining changes to files.
+ */
+ if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE)
+ return false;
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
@@ -1187,12 +1194,7 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
startTime = GetCurrentTimestamp();
else if (TimestampDifferenceExceeds(startTime, GetCurrentTimestamp(),
SHM_SEND_TIMEOUT_MS))
- {
- ereport(LOG,
- (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
- winfo->shared->xid)));
return false;
- }
}
}
@@ -1206,6 +1208,10 @@ void
pa_switch_to_partial_serialize(ParallelApplyWorkerInfo *winfo,
bool stream_locked)
{
+ ereport(LOG,
+ (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
+ winfo->shared->xid)));
+
/*
* The parallel apply worker could be stuck for some reason (say waiting
* on some lock by other backend), so stop trying to send data directly to
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index d1dc2d4..4063051 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -4909,8 +4909,14 @@ struct config_enum ConfigureNamesEnum[] =
{
{"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Allows streaming or serializing each change in logical decoding."),
- NULL,
+ gettext_noop("Controls the behavior of logical replication publisher and subscriber"),
+ gettext_noop("If set to immediate, on the publisher side, it "
+ "allows streaming or serializing each change in "
+ "logical decoding. On the subscriber side, in "
+ "parallel streaming mode, it allows the leader apply "
+ "worker to serialize changes to files and notifies "
+ "the parallel apply workers to read and apply them at "
+ "the end of the transaction."),
GUC_NOT_IN_SAMPLE
},
&logical_replication_mode,
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8..c591cfe 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -312,6 +312,33 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(15000), 'all changes are replayed from file');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index 814daf4..455fde2 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -143,15 +143,17 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c INT, d INT, e INT)");
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -198,6 +200,63 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0), 'check rollback was reflected on subscriber');
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'check rollback to savepoint was reflected on subscriber');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 497245a..9f046e1 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -319,16 +319,18 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber (columns a and b are compatible with same table name on publisher)
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999)"
);
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication (streaming = on)
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -384,6 +386,47 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'transaction is committed on subscriber');
+
###############################
# check all the cleanup
###############################
--
2.7.2.windows.1
[application/octet-stream] v87-0001-Rename-logical_decoding_mode-to-logical_replicat.patch (9.7K, ../../OS0PR01MB57167F14EED6B95582155D9194C99@OS0PR01MB5716.jpnprd01.prod.outlook.com/5-v87-0001-Rename-logical_decoding_mode-to-logical_replicat.patch)
download | inline diff:
From bbcf658604b4995f7aa2e5f9c2f9d9f78036ec45 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 20 Jan 2023 14:39:38 +0800
Subject: [PATCH v87 1/2] Rename logical_decoding_mode to
logical_replication_mode
Rename the developer option 'logical_decoding_mode' to the more
flexible name 'logical_replication_mode' because doing so will make it
easier to extend this option in future to help test other areas of
logical replication.
---
doc/src/sgml/config.sgml | 8 ++++----
src/backend/replication/logical/reorderbuffer.c | 14 +++++++-------
src/backend/utils/misc/guc_tables.c | 12 ++++++------
src/include/replication/reorderbuffer.h | 10 +++++-----
src/test/subscription/t/016_stream_subxact.pl | 2 +-
src/test/subscription/t/018_stream_subxact_abort.pl | 2 +-
src/test/subscription/t/019_stream_subxact_ddl_abort.pl | 2 +-
src/test/subscription/t/023_twophase_stream.pl | 2 +-
src/tools/pgindent/typedefs.list | 2 +-
9 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 89d53f2..c2c5877 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11655,16 +11655,16 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
- <varlistentry id="guc-logical-decoding-mode" xreflabel="logical_decoding_mode">
- <term><varname>logical_decoding_mode</varname> (<type>enum</type>)
+ <varlistentry id="guc-logical-replication-mode" xreflabel="logical_replication_mode">
+ <term><varname>logical_replication_mode</varname> (<type>enum</type>)
<indexterm>
- <primary><varname>logical_decoding_mode</varname> configuration parameter</primary>
+ <primary><varname>logical_replication_mode</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Allows streaming or serializing changes immediately in logical decoding.
- The allowed values of <varname>logical_decoding_mode</varname> are
+ The allowed values of <varname>logical_replication_mode</varname> are
<literal>buffered</literal> and <literal>immediate</literal>. When set
to <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 54ee824..efe057b 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -210,7 +210,7 @@ int logical_decoding_work_mem;
static const Size max_changes_in_memory = 4096; /* XXX for restore only */
/* GUC variable */
-int logical_decoding_mode = LOGICAL_DECODING_MODE_BUFFERED;
+int logical_replication_mode = LOGICAL_REP_MODE_BUFFERED;
/* ---------------------------------------
* primary reorderbuffer support routines
@@ -3552,8 +3552,8 @@ ReorderBufferLargestStreamableTopTXN(ReorderBuffer *rb)
* pick the largest (sub)transaction at-a-time to evict and spill its changes to
* disk or send to the output plugin until we reach under the memory limit.
*
- * If logical_decoding_mode is set to "immediate", stream or serialize the changes
- * immediately.
+ * If logical_replication_mode is set to "immediate", stream or serialize the
+ * changes immediately.
*
* XXX At this point we select the transactions until we reach under the memory
* limit, but we might also adapt a more elaborate eviction strategy - for example
@@ -3566,15 +3566,15 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
ReorderBufferTXN *txn;
/*
- * Bail out if logical_decoding_mode is buffered and we haven't exceeded
+ * Bail out if logical_replication_mode is buffered and we haven't exceeded
* the memory limit.
*/
- if (logical_decoding_mode == LOGICAL_DECODING_MODE_BUFFERED &&
+ if (logical_replication_mode == LOGICAL_REP_MODE_BUFFERED &&
rb->size < logical_decoding_work_mem * 1024L)
return;
/*
- * If logical_decoding_mode is immediate, loop until there's no change.
+ * If logical_replication_mode is immediate, loop until there's no change.
* Otherwise, loop until we reach under the memory limit. One might think
* that just by evicting the largest (sub)transaction we will come under
* the memory limit based on assumption that the selected transaction is
@@ -3584,7 +3584,7 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
* change.
*/
while (rb->size >= logical_decoding_work_mem * 1024L ||
- (logical_decoding_mode == LOGICAL_DECODING_MODE_IMMEDIATE &&
+ (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE &&
rb->size > 0))
{
/*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index cd0fc2c..d1dc2d4 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -395,9 +395,9 @@ static const struct config_enum_entry ssl_protocol_versions_info[] = {
{NULL, 0, false}
};
-static const struct config_enum_entry logical_decoding_mode_options[] = {
- {"buffered", LOGICAL_DECODING_MODE_BUFFERED, false},
- {"immediate", LOGICAL_DECODING_MODE_IMMEDIATE, false},
+static const struct config_enum_entry logical_replication_mode_options[] = {
+ {"buffered", LOGICAL_REP_MODE_BUFFERED, false},
+ {"immediate", LOGICAL_REP_MODE_IMMEDIATE, false},
{NULL, 0, false}
};
@@ -4908,13 +4908,13 @@ struct config_enum ConfigureNamesEnum[] =
},
{
- {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
+ {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
gettext_noop("Allows streaming or serializing each change in logical decoding."),
NULL,
GUC_NOT_IN_SAMPLE
},
- &logical_decoding_mode,
- LOGICAL_DECODING_MODE_BUFFERED, logical_decoding_mode_options,
+ &logical_replication_mode,
+ LOGICAL_REP_MODE_BUFFERED, logical_replication_mode_options,
NULL, NULL, NULL
},
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index f6c4dd7..5a26ec9 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -18,14 +18,14 @@
#include "utils/timestamp.h"
extern PGDLLIMPORT int logical_decoding_work_mem;
-extern PGDLLIMPORT int logical_decoding_mode;
+extern PGDLLIMPORT int logical_replication_mode;
-/* possible values for logical_decoding_mode */
+/* possible values for logical_replication_mode */
typedef enum
{
- LOGICAL_DECODING_MODE_BUFFERED,
- LOGICAL_DECODING_MODE_IMMEDIATE
-} LogicalDecodingMode;
+ LOGICAL_REP_MODE_BUFFERED,
+ LOGICAL_REP_MODE_IMMEDIATE
+} LogicalRepMode;
/* an individual tuple, stored in one chunk of memory */
typedef struct ReorderBufferTupleBuf
diff --git a/src/test/subscription/t/016_stream_subxact.pl b/src/test/subscription/t/016_stream_subxact.pl
index 2f0148c..d830f26 100644
--- a/src/test/subscription/t/016_stream_subxact.pl
+++ b/src/test/subscription/t/016_stream_subxact.pl
@@ -79,7 +79,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index dce14b1..814daf4 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -130,7 +130,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
index b30223d..d0e556c 100644
--- a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
+++ b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
@@ -16,7 +16,7 @@ use Test::More;
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 75ca837..497245a 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -301,7 +301,7 @@ $node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf(
'postgresql.conf', qq(
max_prepared_transactions = 10
-logical_decoding_mode = immediate
+logical_replication_mode = immediate
));
$node_publisher->start;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 0931603..7d15368 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1456,7 +1456,6 @@ LogicalDecodeStreamStopCB
LogicalDecodeStreamTruncateCB
LogicalDecodeTruncateCB
LogicalDecodingContext
-LogicalDecodingMode
LogicalErrorCallbackState
LogicalOutputPluginInit
LogicalOutputPluginWriterPrepareWrite
@@ -1466,6 +1465,7 @@ LogicalRepBeginData
LogicalRepCommitData
LogicalRepCommitPreparedTxnData
LogicalRepCtxStruct
+LogicalRepMode
LogicalRepMsgType
LogicalRepPartMapEntry
LogicalRepPreparedTxnData
--
2.7.2.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-24 12:49 ` [email protected] <[email protected]>
2023-01-24 14:34 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-24 21:45 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
0 siblings, 3 replies; 105+ messages in thread
From: [email protected] @ 2023-01-24 12:49 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Tuesday, January 24, 2023 8:47 PM Hou, Zhijie wrote:
>
> On Tuesday, January 24, 2023 3:19 PM Peter Smith <[email protected]>
> wrote:
> >
> > Here are some review comments for v86-0002
> >
Sorry, the patch set was somehow attached twice. Here is the correct new version
patch set which addressed all comments so far.
Best Regards,
Hou zj
Attachments:
[application/octet-stream] v87-0001-Rename-logical_decoding_mode-to-logical_replicat.patch (9.7K, ../../OS0PR01MB57168ADE4F156E1D65795ECF94C99@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v87-0001-Rename-logical_decoding_mode-to-logical_replicat.patch)
download | inline diff:
From bbcf658604b4995f7aa2e5f9c2f9d9f78036ec45 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 20 Jan 2023 14:39:38 +0800
Subject: [PATCH v87 1/2] Rename logical_decoding_mode to
logical_replication_mode
Rename the developer option 'logical_decoding_mode' to the more
flexible name 'logical_replication_mode' because doing so will make it
easier to extend this option in future to help test other areas of
logical replication.
---
doc/src/sgml/config.sgml | 8 ++++----
src/backend/replication/logical/reorderbuffer.c | 14 +++++++-------
src/backend/utils/misc/guc_tables.c | 12 ++++++------
src/include/replication/reorderbuffer.h | 10 +++++-----
src/test/subscription/t/016_stream_subxact.pl | 2 +-
src/test/subscription/t/018_stream_subxact_abort.pl | 2 +-
src/test/subscription/t/019_stream_subxact_ddl_abort.pl | 2 +-
src/test/subscription/t/023_twophase_stream.pl | 2 +-
src/tools/pgindent/typedefs.list | 2 +-
9 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 89d53f2..c2c5877 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11655,16 +11655,16 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
- <varlistentry id="guc-logical-decoding-mode" xreflabel="logical_decoding_mode">
- <term><varname>logical_decoding_mode</varname> (<type>enum</type>)
+ <varlistentry id="guc-logical-replication-mode" xreflabel="logical_replication_mode">
+ <term><varname>logical_replication_mode</varname> (<type>enum</type>)
<indexterm>
- <primary><varname>logical_decoding_mode</varname> configuration parameter</primary>
+ <primary><varname>logical_replication_mode</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Allows streaming or serializing changes immediately in logical decoding.
- The allowed values of <varname>logical_decoding_mode</varname> are
+ The allowed values of <varname>logical_replication_mode</varname> are
<literal>buffered</literal> and <literal>immediate</literal>. When set
to <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 54ee824..efe057b 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -210,7 +210,7 @@ int logical_decoding_work_mem;
static const Size max_changes_in_memory = 4096; /* XXX for restore only */
/* GUC variable */
-int logical_decoding_mode = LOGICAL_DECODING_MODE_BUFFERED;
+int logical_replication_mode = LOGICAL_REP_MODE_BUFFERED;
/* ---------------------------------------
* primary reorderbuffer support routines
@@ -3552,8 +3552,8 @@ ReorderBufferLargestStreamableTopTXN(ReorderBuffer *rb)
* pick the largest (sub)transaction at-a-time to evict and spill its changes to
* disk or send to the output plugin until we reach under the memory limit.
*
- * If logical_decoding_mode is set to "immediate", stream or serialize the changes
- * immediately.
+ * If logical_replication_mode is set to "immediate", stream or serialize the
+ * changes immediately.
*
* XXX At this point we select the transactions until we reach under the memory
* limit, but we might also adapt a more elaborate eviction strategy - for example
@@ -3566,15 +3566,15 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
ReorderBufferTXN *txn;
/*
- * Bail out if logical_decoding_mode is buffered and we haven't exceeded
+ * Bail out if logical_replication_mode is buffered and we haven't exceeded
* the memory limit.
*/
- if (logical_decoding_mode == LOGICAL_DECODING_MODE_BUFFERED &&
+ if (logical_replication_mode == LOGICAL_REP_MODE_BUFFERED &&
rb->size < logical_decoding_work_mem * 1024L)
return;
/*
- * If logical_decoding_mode is immediate, loop until there's no change.
+ * If logical_replication_mode is immediate, loop until there's no change.
* Otherwise, loop until we reach under the memory limit. One might think
* that just by evicting the largest (sub)transaction we will come under
* the memory limit based on assumption that the selected transaction is
@@ -3584,7 +3584,7 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
* change.
*/
while (rb->size >= logical_decoding_work_mem * 1024L ||
- (logical_decoding_mode == LOGICAL_DECODING_MODE_IMMEDIATE &&
+ (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE &&
rb->size > 0))
{
/*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index cd0fc2c..d1dc2d4 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -395,9 +395,9 @@ static const struct config_enum_entry ssl_protocol_versions_info[] = {
{NULL, 0, false}
};
-static const struct config_enum_entry logical_decoding_mode_options[] = {
- {"buffered", LOGICAL_DECODING_MODE_BUFFERED, false},
- {"immediate", LOGICAL_DECODING_MODE_IMMEDIATE, false},
+static const struct config_enum_entry logical_replication_mode_options[] = {
+ {"buffered", LOGICAL_REP_MODE_BUFFERED, false},
+ {"immediate", LOGICAL_REP_MODE_IMMEDIATE, false},
{NULL, 0, false}
};
@@ -4908,13 +4908,13 @@ struct config_enum ConfigureNamesEnum[] =
},
{
- {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
+ {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
gettext_noop("Allows streaming or serializing each change in logical decoding."),
NULL,
GUC_NOT_IN_SAMPLE
},
- &logical_decoding_mode,
- LOGICAL_DECODING_MODE_BUFFERED, logical_decoding_mode_options,
+ &logical_replication_mode,
+ LOGICAL_REP_MODE_BUFFERED, logical_replication_mode_options,
NULL, NULL, NULL
},
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index f6c4dd7..5a26ec9 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -18,14 +18,14 @@
#include "utils/timestamp.h"
extern PGDLLIMPORT int logical_decoding_work_mem;
-extern PGDLLIMPORT int logical_decoding_mode;
+extern PGDLLIMPORT int logical_replication_mode;
-/* possible values for logical_decoding_mode */
+/* possible values for logical_replication_mode */
typedef enum
{
- LOGICAL_DECODING_MODE_BUFFERED,
- LOGICAL_DECODING_MODE_IMMEDIATE
-} LogicalDecodingMode;
+ LOGICAL_REP_MODE_BUFFERED,
+ LOGICAL_REP_MODE_IMMEDIATE
+} LogicalRepMode;
/* an individual tuple, stored in one chunk of memory */
typedef struct ReorderBufferTupleBuf
diff --git a/src/test/subscription/t/016_stream_subxact.pl b/src/test/subscription/t/016_stream_subxact.pl
index 2f0148c..d830f26 100644
--- a/src/test/subscription/t/016_stream_subxact.pl
+++ b/src/test/subscription/t/016_stream_subxact.pl
@@ -79,7 +79,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index dce14b1..814daf4 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -130,7 +130,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
index b30223d..d0e556c 100644
--- a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
+++ b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
@@ -16,7 +16,7 @@ use Test::More;
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 75ca837..497245a 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -301,7 +301,7 @@ $node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf(
'postgresql.conf', qq(
max_prepared_transactions = 10
-logical_decoding_mode = immediate
+logical_replication_mode = immediate
));
$node_publisher->start;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 0931603..7d15368 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1456,7 +1456,6 @@ LogicalDecodeStreamStopCB
LogicalDecodeStreamTruncateCB
LogicalDecodeTruncateCB
LogicalDecodingContext
-LogicalDecodingMode
LogicalErrorCallbackState
LogicalOutputPluginInit
LogicalOutputPluginWriterPrepareWrite
@@ -1466,6 +1465,7 @@ LogicalRepBeginData
LogicalRepCommitData
LogicalRepCommitPreparedTxnData
LogicalRepCtxStruct
+LogicalRepMode
LogicalRepMsgType
LogicalRepPartMapEntry
LogicalRepPreparedTxnData
--
2.7.2.windows.1
[application/octet-stream] v87-0002-Extend-the-logical_replication_mode-to-test-the-.patch (13.9K, ../../OS0PR01MB57168ADE4F156E1D65795ECF94C99@OS0PR01MB5716.jpnprd01.prod.outlook.com/3-v87-0002-Extend-the-logical_replication_mode-to-test-the-.patch)
download | inline diff:
From f6b35de201dd4f094b78c83da044dc9f077cbd28 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 20 Jan 2023 16:59:37 +0800
Subject: [PATCH v87 2/2] Extend the logical_replication_mode to test the
stream parallel mode
Give additional functionality to the existing developer option
'logical_replication_mode' to help test parallel apply of large
transactions on the subscriber.
When set to 'buffered', the leader sends changes to parallel apply workers via
shared memory queue. When set to 'immediate', the leader serializes all changes
to files and notifies the parallel apply workers to read and apply them at the
end of the transaction.
This helps in adding tests to cover the serialization code path in parallel
streaming mode.
---
doc/src/sgml/config.sgml | 31 ++++++++---
.../replication/logical/applyparallelworker.c | 16 ++++--
src/backend/utils/misc/guc_tables.c | 10 +++-
src/test/subscription/t/015_stream.pl | 27 ++++++++++
.../subscription/t/018_stream_subxact_abort.pl | 61 +++++++++++++++++++++-
src/test/subscription/t/023_twophase_stream.pl | 45 +++++++++++++++-
6 files changed, 174 insertions(+), 16 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index c2c5877..5cdc3e9 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11663,22 +11663,39 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</term>
<listitem>
<para>
- Allows streaming or serializing changes immediately in logical decoding.
The allowed values of <varname>logical_replication_mode</varname> are
- <literal>buffered</literal> and <literal>immediate</literal>. When set
- to <literal>immediate</literal>, stream each change if
+ <literal>buffered</literal> and <literal>immediate</literal>. The default
+ is <literal>buffered</literal>.
+ </para>
+
+ <para>
+ On the publisher side, it allows streaming or serializing changes
+ immediately in logical decoding. When set to
+ <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
<link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link>)
is enabled, otherwise, serialize each change. When set to
- <literal>buffered</literal>, which is the default, decoding will stream
- or serialize changes when <varname>logical_decoding_work_mem</varname>
- is reached.
+ <literal>buffered</literal>, decoding will stream or serialize changes
+ when <varname>logical_decoding_work_mem</varname> is reached.
</para>
+
+ <para>
+ On the subscriber side, if <literal>streaming</literal> option is set
+ to <literal>parallel</literal>, this parameter also allows the leader
+ apply worker to send changes to the shared memory queue or to serialize
+ changes. When set to <literal>buffered</literal>, the leader sends
+ changes to parallel apply workers via shared memory queue. When set to
+ <literal>immediate</literal>, the leader serializes all changes to
+ files and notifies the parallel apply workers to read and apply them at
+ the end of the transaction.
+ </para>
+
<para>
This parameter is intended to be used to test logical decoding and
replication of large transactions for which otherwise we need to
generate the changes till <varname>logical_decoding_work_mem</varname>
- is reached.
+ is reached. Moreover, this can also be used to test the transmission of
+ changes between the leader and parallel apply workers.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3579e70..17a8fd3 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -1149,6 +1149,13 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ /*
+ * In immeidate mode, directly return false so that we can switch to
+ * PARTIAL_SERIALIZE mode and serialize remaining changes to files.
+ */
+ if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE)
+ return false;
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
@@ -1187,12 +1194,7 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
startTime = GetCurrentTimestamp();
else if (TimestampDifferenceExceeds(startTime, GetCurrentTimestamp(),
SHM_SEND_TIMEOUT_MS))
- {
- ereport(LOG,
- (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
- winfo->shared->xid)));
return false;
- }
}
}
@@ -1206,6 +1208,10 @@ void
pa_switch_to_partial_serialize(ParallelApplyWorkerInfo *winfo,
bool stream_locked)
{
+ ereport(LOG,
+ (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
+ winfo->shared->xid)));
+
/*
* The parallel apply worker could be stuck for some reason (say waiting
* on some lock by other backend), so stop trying to send data directly to
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index d1dc2d4..4063051 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -4909,8 +4909,14 @@ struct config_enum ConfigureNamesEnum[] =
{
{"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Allows streaming or serializing each change in logical decoding."),
- NULL,
+ gettext_noop("Controls the behavior of logical replication publisher and subscriber"),
+ gettext_noop("If set to immediate, on the publisher side, it "
+ "allows streaming or serializing each change in "
+ "logical decoding. On the subscriber side, in "
+ "parallel streaming mode, it allows the leader apply "
+ "worker to serialize changes to files and notifies "
+ "the parallel apply workers to read and apply them at "
+ "the end of the transaction."),
GUC_NOT_IN_SAMPLE
},
&logical_replication_mode,
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8..c591cfe 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -312,6 +312,33 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(15000), 'all changes are replayed from file');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index 814daf4..455fde2 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -143,15 +143,17 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c INT, d INT, e INT)");
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -198,6 +200,63 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0), 'check rollback was reflected on subscriber');
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'check rollback to savepoint was reflected on subscriber');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 497245a..9f046e1 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -319,16 +319,18 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber (columns a and b are compatible with same table name on publisher)
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999)"
);
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication (streaming = on)
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -384,6 +386,47 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'transaction is committed on subscriber');
+
###############################
# check all the cleanup
###############################
--
2.7.2.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-24 14:34 ` Hayato Kuroda (Fujitsu) <[email protected]>
2 siblings, 0 replies; 105+ messages in thread
From: Hayato Kuroda (Fujitsu) @ 2023-01-24 14:34 UTC (permalink / raw)
To: [email protected] <[email protected]>; Peter Smith <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
Dear Hou,
> Sorry, the patch set was somehow attached twice. Here is the correct new version
> patch set which addressed all comments so far.
Thank you for updating the patch! I confirmed that
All of my comments are addressed.
One comment:
In this test the rollback-prepared seems not to be executed.
This is because serializations are finished while handling PREPARE message
and the final state of transaction does not affect that, right?
I think it may be helpful to add a one line comment.
Best Regards,
Hayato Kuroda
FUJITSU LIMITED
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-24 21:45 ` Peter Smith <[email protected]>
2023-01-25 04:35 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Peter Smith @ 2023-01-24 21:45 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Tue, Jan 24, 2023 at 11:49 PM [email protected]
<[email protected]> wrote:
>
...
>
> Sorry, the patch set was somehow attached twice. Here is the correct new version
> patch set which addressed all comments so far.
>
Here are my review comments for patch v87-0001.
======
src/backend/replication/logical/reorderbuffer.c
1.
@@ -210,7 +210,7 @@ int logical_decoding_work_mem;
static const Size max_changes_in_memory = 4096; /* XXX for restore only */
/* GUC variable */
-int logical_decoding_mode = LOGICAL_DECODING_MODE_BUFFERED;
+int logical_replication_mode = LOGICAL_REP_MODE_BUFFERED;
I noticed that the comment /* GUC variable */ is currently only above
the logical_replication_mode, but actually logical_decoding_work_mem
is a GUC variable too. Maybe this should be rearranged somehow then
change the comment "GUC variable" -> "GUC variables"?
======
src/backend/utils/misc/guc_tables.c
@@ -4908,13 +4908,13 @@ struct config_enum ConfigureNamesEnum[] =
},
{
- {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
+ {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
gettext_noop("Allows streaming or serializing each change in logical
decoding."),
NULL,
GUC_NOT_IN_SAMPLE
},
- &logical_decoding_mode,
- LOGICAL_DECODING_MODE_BUFFERED, logical_decoding_mode_options,
+ &logical_replication_mode,
+ LOGICAL_REP_MODE_BUFFERED, logical_replication_mode_options,
NULL, NULL, NULL
},
That gettext_noop string seems incorrect. I think Kuroda-san
previously reported the same, but then you replied it has been fixed
already [1]
> I felt the description seems not to be suitable for current behavior.
> A short description should be like "Sets a behavior of logical replication", and
> further descriptions can be added in lond description.
I adjusted the description here.
But this doesn't look fixed to me. (??)
======
src/include/replication/reorderbuffer.h
3.
@@ -18,14 +18,14 @@
#include "utils/timestamp.h"
extern PGDLLIMPORT int logical_decoding_work_mem;
-extern PGDLLIMPORT int logical_decoding_mode;
+extern PGDLLIMPORT int logical_replication_mode;
Probably here should also be a comment to say "/* GUC variables */"
------
[1] https://www.postgresql.org/message-id/OS0PR01MB5716AE9F095F9E7888987BC794C99%40OS0PR01MB5716.jpnprd0...
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 21:45 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-25 04:35 ` Amit Kapila <[email protected]>
2023-01-25 06:27 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-01-25 04:35 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Wed, Jan 25, 2023 at 3:15 AM Peter Smith <[email protected]> wrote:
>
> 1.
> @@ -210,7 +210,7 @@ int logical_decoding_work_mem;
> static const Size max_changes_in_memory = 4096; /* XXX for restore only */
>
> /* GUC variable */
> -int logical_decoding_mode = LOGICAL_DECODING_MODE_BUFFERED;
> +int logical_replication_mode = LOGICAL_REP_MODE_BUFFERED;
>
>
> I noticed that the comment /* GUC variable */ is currently only above
> the logical_replication_mode, but actually logical_decoding_work_mem
> is a GUC variable too. Maybe this should be rearranged somehow then
> change the comment "GUC variable" -> "GUC variables"?
>
I think moving these variables together doesn't sound like a good idea
because logical_decoding_work_mem variable is defined with other
related variable. Also, if we are doing the last comment, I think that
will obviate the need for this.
> ======
> src/backend/utils/misc/guc_tables.c
>
> @@ -4908,13 +4908,13 @@ struct config_enum ConfigureNamesEnum[] =
> },
>
> {
> - {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
> + {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
> gettext_noop("Allows streaming or serializing each change in logical
> decoding."),
> NULL,
> GUC_NOT_IN_SAMPLE
> },
> - &logical_decoding_mode,
> - LOGICAL_DECODING_MODE_BUFFERED, logical_decoding_mode_options,
> + &logical_replication_mode,
> + LOGICAL_REP_MODE_BUFFERED, logical_replication_mode_options,
> NULL, NULL, NULL
> },
>
> That gettext_noop string seems incorrect. I think Kuroda-san
> previously reported the same, but then you replied it has been fixed
> already [1]
>
> > I felt the description seems not to be suitable for current behavior.
> > A short description should be like "Sets a behavior of logical replication", and
> > further descriptions can be added in lond description.
> I adjusted the description here.
>
> But this doesn't look fixed to me. (??)
>
Okay, so, how about the following for the 0001 patch:
short desc: Controls when to replicate each change.
long desc: On the publisher, it allows streaming or serializing each
change in logical decoding.
Then we can extend it as follows for the 0002 patch:
Controls when to replicate or apply each change
On the publisher, it allows streaming or serializing each change in
logical decoding. On the subscriber, it allows serialization of all
changes to files and notifies the parallel apply workers to read and
apply them at the end of the transaction.
> ======
> src/include/replication/reorderbuffer.h
>
> 3.
> @@ -18,14 +18,14 @@
> #include "utils/timestamp.h"
>
> extern PGDLLIMPORT int logical_decoding_work_mem;
> -extern PGDLLIMPORT int logical_decoding_mode;
> +extern PGDLLIMPORT int logical_replication_mode;
>
> Probably here should also be a comment to say "/* GUC variables */"
>
Okay, we can do this.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 21:45 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 04:35 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-25 06:27 ` Amit Kapila <[email protected]>
2023-01-25 06:51 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-27 16:36 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 2 replies; 105+ messages in thread
From: Amit Kapila @ 2023-01-25 06:27 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Wed, Jan 25, 2023 at 10:05 AM Amit Kapila <[email protected]> wrote:
>
> On Wed, Jan 25, 2023 at 3:15 AM Peter Smith <[email protected]> wrote:
> >
> > 1.
> > @@ -210,7 +210,7 @@ int logical_decoding_work_mem;
> > static const Size max_changes_in_memory = 4096; /* XXX for restore only */
> >
> > /* GUC variable */
> > -int logical_decoding_mode = LOGICAL_DECODING_MODE_BUFFERED;
> > +int logical_replication_mode = LOGICAL_REP_MODE_BUFFERED;
> >
> >
> > I noticed that the comment /* GUC variable */ is currently only above
> > the logical_replication_mode, but actually logical_decoding_work_mem
> > is a GUC variable too. Maybe this should be rearranged somehow then
> > change the comment "GUC variable" -> "GUC variables"?
> >
>
> I think moving these variables together doesn't sound like a good idea
> because logical_decoding_work_mem variable is defined with other
> related variable. Also, if we are doing the last comment, I think that
> will obviate the need for this.
>
> > ======
> > src/backend/utils/misc/guc_tables.c
> >
> > @@ -4908,13 +4908,13 @@ struct config_enum ConfigureNamesEnum[] =
> > },
> >
> > {
> > - {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
> > + {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
> > gettext_noop("Allows streaming or serializing each change in logical
> > decoding."),
> > NULL,
> > GUC_NOT_IN_SAMPLE
> > },
> > - &logical_decoding_mode,
> > - LOGICAL_DECODING_MODE_BUFFERED, logical_decoding_mode_options,
> > + &logical_replication_mode,
> > + LOGICAL_REP_MODE_BUFFERED, logical_replication_mode_options,
> > NULL, NULL, NULL
> > },
> >
> > That gettext_noop string seems incorrect. I think Kuroda-san
> > previously reported the same, but then you replied it has been fixed
> > already [1]
> >
> > > I felt the description seems not to be suitable for current behavior.
> > > A short description should be like "Sets a behavior of logical replication", and
> > > further descriptions can be added in lond description.
> > I adjusted the description here.
> >
> > But this doesn't look fixed to me. (??)
> >
>
> Okay, so, how about the following for the 0001 patch:
> short desc: Controls when to replicate each change.
> long desc: On the publisher, it allows streaming or serializing each
> change in logical decoding.
>
I have updated the patch accordingly and it looks good to me. I'll
push this first patch early next week (Monday) unless there are more
comments.
--
With Regards,
Amit Kapila.
Attachments:
[application/octet-stream] v88-0001-Rename-GUC-logical_decoding_mode-to-logical_repl.patch (10.9K, ../../CAA4eK1JpWoaB63YULpQa1KDw_zBW-QoRMuNxuiP1KafPJzuVuw@mail.gmail.com/2-v88-0001-Rename-GUC-logical_decoding_mode-to-logical_repl.patch)
download | inline diff:
From 9c1534d65386857b0b5e7d91631b44c35b1e72c5 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 20 Jan 2023 14:39:38 +0800
Subject: [PATCH v88] Rename GUC logical_decoding_mode to
logical_replication_mode.
Rename the developer option 'logical_decoding_mode' to the more flexible
name 'logical_replication_mode' because doing so will make it easier to
extend this option in the future to help test other areas of logical
replication.
Currently, it is used on the publisher side to allow streaming or
serializing each change in logical decoding. In the upcoming patch, we are
planning to use it on the subscriber. On the subscriber, it will allow
serializing the changes to file and notifies the parallel apply workers to
read and apply them at the end of the transaction.
We have discussed having this parameter as a subscription option but
exposing a parameter that is primarily used for testing/debugging to users
didn't seem advisable and there is no other such parameter. The other
option we have discussed is to have a separate GUC for subscriber-side
testing but it appears that for the current testing existing parameter is
sufficient and avoids adding another GUC.
Author: Hou Zhijie
Reviewed-by: Pater Smith, Kuroda Hayato, Amit Kapila
Discussion: https://postgr.es/m/CAD21AoAy2c=Mx=FTCs+EwUsf2kQL5MmU3N18X84k0EmCXntK4g@mail.gmail.com
Discussion: https://postgr.es/m/CAA4eK1+wyN6zpaHUkCLorEWNx75MG0xhMwcFhvjqm2KURZEAGw@mail.gmail.com
---
doc/src/sgml/config.sgml | 8 ++++----
src/backend/replication/logical/reorderbuffer.c | 14 +++++++-------
src/backend/utils/misc/guc_tables.c | 16 ++++++++--------
src/include/replication/reorderbuffer.h | 11 ++++++-----
src/test/subscription/t/016_stream_subxact.pl | 2 +-
.../subscription/t/018_stream_subxact_abort.pl | 2 +-
.../t/019_stream_subxact_ddl_abort.pl | 2 +-
src/test/subscription/t/023_twophase_stream.pl | 2 +-
src/tools/pgindent/typedefs.list | 2 +-
9 files changed, 30 insertions(+), 29 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index f985afc009..1cf53c74ea 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11693,16 +11693,16 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
- <varlistentry id="guc-logical-decoding-mode" xreflabel="logical_decoding_mode">
- <term><varname>logical_decoding_mode</varname> (<type>enum</type>)
+ <varlistentry id="guc-logical-replication-mode" xreflabel="logical_replication_mode">
+ <term><varname>logical_replication_mode</varname> (<type>enum</type>)
<indexterm>
- <primary><varname>logical_decoding_mode</varname> configuration parameter</primary>
+ <primary><varname>logical_replication_mode</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Allows streaming or serializing changes immediately in logical decoding.
- The allowed values of <varname>logical_decoding_mode</varname> are
+ The allowed values of <varname>logical_replication_mode</varname> are
<literal>buffered</literal> and <literal>immediate</literal>. When set
to <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 54ee824e6c..efe057b4de 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -210,7 +210,7 @@ int logical_decoding_work_mem;
static const Size max_changes_in_memory = 4096; /* XXX for restore only */
/* GUC variable */
-int logical_decoding_mode = LOGICAL_DECODING_MODE_BUFFERED;
+int logical_replication_mode = LOGICAL_REP_MODE_BUFFERED;
/* ---------------------------------------
* primary reorderbuffer support routines
@@ -3552,8 +3552,8 @@ ReorderBufferLargestStreamableTopTXN(ReorderBuffer *rb)
* pick the largest (sub)transaction at-a-time to evict and spill its changes to
* disk or send to the output plugin until we reach under the memory limit.
*
- * If logical_decoding_mode is set to "immediate", stream or serialize the changes
- * immediately.
+ * If logical_replication_mode is set to "immediate", stream or serialize the
+ * changes immediately.
*
* XXX At this point we select the transactions until we reach under the memory
* limit, but we might also adapt a more elaborate eviction strategy - for example
@@ -3566,15 +3566,15 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
ReorderBufferTXN *txn;
/*
- * Bail out if logical_decoding_mode is buffered and we haven't exceeded
+ * Bail out if logical_replication_mode is buffered and we haven't exceeded
* the memory limit.
*/
- if (logical_decoding_mode == LOGICAL_DECODING_MODE_BUFFERED &&
+ if (logical_replication_mode == LOGICAL_REP_MODE_BUFFERED &&
rb->size < logical_decoding_work_mem * 1024L)
return;
/*
- * If logical_decoding_mode is immediate, loop until there's no change.
+ * If logical_replication_mode is immediate, loop until there's no change.
* Otherwise, loop until we reach under the memory limit. One might think
* that just by evicting the largest (sub)transaction we will come under
* the memory limit based on assumption that the selected transaction is
@@ -3584,7 +3584,7 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
* change.
*/
while (rb->size >= logical_decoding_work_mem * 1024L ||
- (logical_decoding_mode == LOGICAL_DECODING_MODE_IMMEDIATE &&
+ (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE &&
rb->size > 0))
{
/*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 4ac808ed22..c5a95f5dcc 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -395,9 +395,9 @@ static const struct config_enum_entry ssl_protocol_versions_info[] = {
{NULL, 0, false}
};
-static const struct config_enum_entry logical_decoding_mode_options[] = {
- {"buffered", LOGICAL_DECODING_MODE_BUFFERED, false},
- {"immediate", LOGICAL_DECODING_MODE_IMMEDIATE, false},
+static const struct config_enum_entry logical_replication_mode_options[] = {
+ {"buffered", LOGICAL_REP_MODE_BUFFERED, false},
+ {"immediate", LOGICAL_REP_MODE_IMMEDIATE, false},
{NULL, 0, false}
};
@@ -4919,13 +4919,13 @@ struct config_enum ConfigureNamesEnum[] =
},
{
- {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Allows streaming or serializing each change in logical decoding."),
- NULL,
+ {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
+ gettext_noop("Controls when to replicate each change."),
+ gettext_noop("On the publisher, it allows streaming or serializing each change in logical decoding."),
GUC_NOT_IN_SAMPLE
},
- &logical_decoding_mode,
- LOGICAL_DECODING_MODE_BUFFERED, logical_decoding_mode_options,
+ &logical_replication_mode,
+ LOGICAL_REP_MODE_BUFFERED, logical_replication_mode_options,
NULL, NULL, NULL
},
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index f6c4dd75db..e5db041df1 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -17,15 +17,16 @@
#include "utils/snapshot.h"
#include "utils/timestamp.h"
+/* GUC variables */
extern PGDLLIMPORT int logical_decoding_work_mem;
-extern PGDLLIMPORT int logical_decoding_mode;
+extern PGDLLIMPORT int logical_replication_mode;
-/* possible values for logical_decoding_mode */
+/* possible values for logical_replication_mode */
typedef enum
{
- LOGICAL_DECODING_MODE_BUFFERED,
- LOGICAL_DECODING_MODE_IMMEDIATE
-} LogicalDecodingMode;
+ LOGICAL_REP_MODE_BUFFERED,
+ LOGICAL_REP_MODE_IMMEDIATE
+} LogicalRepMode;
/* an individual tuple, stored in one chunk of memory */
typedef struct ReorderBufferTupleBuf
diff --git a/src/test/subscription/t/016_stream_subxact.pl b/src/test/subscription/t/016_stream_subxact.pl
index 2f0148c3a8..d830f26e06 100644
--- a/src/test/subscription/t/016_stream_subxact.pl
+++ b/src/test/subscription/t/016_stream_subxact.pl
@@ -79,7 +79,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index dce14b150a..814daf4d2f 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -130,7 +130,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
index b30223de51..d0e556c8b8 100644
--- a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
+++ b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
@@ -16,7 +16,7 @@ use Test::More;
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 75ca83765e..497245a209 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -301,7 +301,7 @@ $node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf(
'postgresql.conf', qq(
max_prepared_transactions = 10
-logical_decoding_mode = immediate
+logical_replication_mode = immediate
));
$node_publisher->start;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 51484ca7e2..07fbb7ccf6 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1458,7 +1458,6 @@ LogicalDecodeStreamStopCB
LogicalDecodeStreamTruncateCB
LogicalDecodeTruncateCB
LogicalDecodingContext
-LogicalDecodingMode
LogicalErrorCallbackState
LogicalOutputPluginInit
LogicalOutputPluginWriterPrepareWrite
@@ -1468,6 +1467,7 @@ LogicalRepBeginData
LogicalRepCommitData
LogicalRepCommitPreparedTxnData
LogicalRepCtxStruct
+LogicalRepMode
LogicalRepMsgType
LogicalRepPartMapEntry
LogicalRepPreparedTxnData
--
2.28.0.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 21:45 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 04:35 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-25 06:27 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-25 06:51 ` Hayato Kuroda (Fujitsu) <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: Hayato Kuroda (Fujitsu) @ 2023-01-25 06:51 UTC (permalink / raw)
To: 'Amit Kapila' <[email protected]>; Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
Dear Amit,
>
> I have updated the patch accordingly and it looks good to me. I'll
> push this first patch early next week (Monday) unless there are more
> comments.
Thanks for updating. I checked v88-0001 and I have no objection. LGTM.
Best Regards,
Hayato Kuroda
FUJITSU LIMITED
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 21:45 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 04:35 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-25 06:27 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-27 16:36 ` Masahiko Sawada <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: Masahiko Sawada @ 2023-01-27 16:36 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Peter Smith <[email protected]>; [email protected] <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Wed, Jan 25, 2023 at 3:27 PM Amit Kapila <[email protected]> wrote:
>
> On Wed, Jan 25, 2023 at 10:05 AM Amit Kapila <[email protected]> wrote:
> >
> > On Wed, Jan 25, 2023 at 3:15 AM Peter Smith <[email protected]> wrote:
> > >
> > > 1.
> > > @@ -210,7 +210,7 @@ int logical_decoding_work_mem;
> > > static const Size max_changes_in_memory = 4096; /* XXX for restore only */
> > >
> > > /* GUC variable */
> > > -int logical_decoding_mode = LOGICAL_DECODING_MODE_BUFFERED;
> > > +int logical_replication_mode = LOGICAL_REP_MODE_BUFFERED;
> > >
> > >
> > > I noticed that the comment /* GUC variable */ is currently only above
> > > the logical_replication_mode, but actually logical_decoding_work_mem
> > > is a GUC variable too. Maybe this should be rearranged somehow then
> > > change the comment "GUC variable" -> "GUC variables"?
> > >
> >
> > I think moving these variables together doesn't sound like a good idea
> > because logical_decoding_work_mem variable is defined with other
> > related variable. Also, if we are doing the last comment, I think that
> > will obviate the need for this.
> >
> > > ======
> > > src/backend/utils/misc/guc_tables.c
> > >
> > > @@ -4908,13 +4908,13 @@ struct config_enum ConfigureNamesEnum[] =
> > > },
> > >
> > > {
> > > - {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
> > > + {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
> > > gettext_noop("Allows streaming or serializing each change in logical
> > > decoding."),
> > > NULL,
> > > GUC_NOT_IN_SAMPLE
> > > },
> > > - &logical_decoding_mode,
> > > - LOGICAL_DECODING_MODE_BUFFERED, logical_decoding_mode_options,
> > > + &logical_replication_mode,
> > > + LOGICAL_REP_MODE_BUFFERED, logical_replication_mode_options,
> > > NULL, NULL, NULL
> > > },
> > >
> > > That gettext_noop string seems incorrect. I think Kuroda-san
> > > previously reported the same, but then you replied it has been fixed
> > > already [1]
> > >
> > > > I felt the description seems not to be suitable for current behavior.
> > > > A short description should be like "Sets a behavior of logical replication", and
> > > > further descriptions can be added in lond description.
> > > I adjusted the description here.
> > >
> > > But this doesn't look fixed to me. (??)
> > >
> >
> > Okay, so, how about the following for the 0001 patch:
> > short desc: Controls when to replicate each change.
> > long desc: On the publisher, it allows streaming or serializing each
> > change in logical decoding.
> >
>
> I have updated the patch accordingly and it looks good to me. I'll
> push this first patch early next week (Monday) unless there are more
> comments.
The patch looks good to me too. Thank you for the patch.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-24 23:30 ` Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Peter Smith @ 2023-01-24 23:30 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
Here are my review comments for patch v87-0002.
======
doc/src/sgml/config.sgml
1.
<para>
- Allows streaming or serializing changes immediately in
logical decoding.
The allowed values of <varname>logical_replication_mode</varname> are
- <literal>buffered</literal> and <literal>immediate</literal>. When set
- to <literal>immediate</literal>, stream each change if
+ <literal>buffered</literal> and <literal>immediate</literal>.
The default
+ is <literal>buffered</literal>.
+ </para>
I didn't think it was necessary to say “of logical_replication_mode”.
IMO that much is already obvious because this is the first sentence of
the description for logical_replication_mode.
(see also review comment #4)
~~~
2.
+ <para>
+ On the publisher side, it allows streaming or serializing changes
+ immediately in logical decoding. When set to
+ <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
<link linkend="sql-createsubscription"><command>CREATE
SUBSCRIPTION</command></link>)
is enabled, otherwise, serialize each change. When set to
- <literal>buffered</literal>, which is the default, decoding will stream
- or serialize changes when <varname>logical_decoding_work_mem</varname>
- is reached.
+ <literal>buffered</literal>, decoding will stream or serialize changes
+ when <varname>logical_decoding_work_mem</varname> is reached.
</para>
2a.
"it allows" --> "logical_replication_mode allows"
2b.
"decoding" --> "the decoding"
~~~
3.
+ <para>
+ On the subscriber side, if <literal>streaming</literal> option is set
+ to <literal>parallel</literal>, this parameter also allows the leader
+ apply worker to send changes to the shared memory queue or to serialize
+ changes. When set to <literal>buffered</literal>, the leader sends
+ changes to parallel apply workers via shared memory queue. When set to
+ <literal>immediate</literal>, the leader serializes all changes to
+ files and notifies the parallel apply workers to read and apply them at
+ the end of the transaction.
+ </para>
"this parameter also allows" --> "logical_replication_mode also allows"
~~~
4.
<para>
This parameter is intended to be used to test logical decoding and
replication of large transactions for which otherwise we need to
generate the changes till <varname>logical_decoding_work_mem</varname>
- is reached.
+ is reached. Moreover, this can also be used to test the transmission of
+ changes between the leader and parallel apply workers.
</para>
"Moreover, this can also" --> "It can also"
I am wondering would this sentence be better put at the top of the GUC
description. So then the first paragraph becomes like this:
SUGGESTION (I've also added another sentence "The effect of...")
The allowed values are buffered and immediate. The default is
buffered. This parameter is intended to be used to test logical
decoding and replication of large transactions for which otherwise we
need to generate the changes till logical_decoding_work_mem is
reached. It can also be used to test the transmission of changes
between the leader and parallel apply workers. The effect of
logical_replication_mode is different for the publisher and
subscriber:
On the publisher side...
On the subscriber side...
======
.../replication/logical/applyparallelworker.c
5.
+ /*
+ * In immeidate mode, directly return false so that we can switch to
+ * PARTIAL_SERIALIZE mode and serialize remaining changes to files.
+ */
+ if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE)
+ return false;
Typo "immediate"
Also, I felt "directly" is not needed. "return false" and "directly
return false" is the same.
SUGGESTION
Using ‘immediate’ mode returns false to cause a switch to
PARTIAL_SERIALIZE mode so that the remaining changes will be
serialized.
======
src/backend/utils/misc/guc_tables.c
6.
{
{"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Allows streaming or serializing each change in logical
decoding."),
- NULL,
+ gettext_noop("Controls the behavior of logical replication publisher
and subscriber"),
+ gettext_noop("If set to immediate, on the publisher side, it "
+ "allows streaming or serializing each change in "
+ "logical decoding. On the subscriber side, in "
+ "parallel streaming mode, it allows the leader apply "
+ "worker to serialize changes to files and notifies "
+ "the parallel apply workers to read and apply them at "
+ "the end of the transaction."),
GUC_NOT_IN_SAMPLE
},
6a. short description
User PoV behaviour should be the same. Instead, maybe say "controls
the internal behavior" or something like that?
~
6b. long description
IMO the long description shouldn’t mention ‘immediate’ mode first as it does.
BEFORE
If set to immediate, on the publisher side, ...
AFTER
On the publisher side, ...
------
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-25 14:24 ` [email protected] <[email protected]>
2023-01-26 03:36 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-30 00:10 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-30 04:12 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
0 siblings, 3 replies; 105+ messages in thread
From: [email protected] @ 2023-01-25 14:24 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Wednesday, January 25, 2023 7:30 AM Peter Smith <[email protected]> wrote:
>
> Here are my review comments for patch v87-0002.
Thanks for your comments.
> ======
> doc/src/sgml/config.sgml
>
> 1.
> <para>
> - Allows streaming or serializing changes immediately in
> logical decoding.
> The allowed values of
> <varname>logical_replication_mode</varname> are
> - <literal>buffered</literal> and <literal>immediate</literal>. When
> set
> - to <literal>immediate</literal>, stream each change if
> + <literal>buffered</literal> and <literal>immediate</literal>.
> The default
> + is <literal>buffered</literal>.
> + </para>
>
> I didn't think it was necessary to say “of logical_replication_mode”.
> IMO that much is already obvious because this is the first sentence of the
> description for logical_replication_mode.
>
Changed.
> ~~~
>
> 2.
> + <para>
> + On the publisher side, it allows streaming or serializing changes
> + immediately in logical decoding. When set to
> + <literal>immediate</literal>, stream each change if
> <literal>streaming</literal> option (see optional parameters set by
> <link linkend="sql-createsubscription"><command>CREATE
> SUBSCRIPTION</command></link>)
> is enabled, otherwise, serialize each change. When set to
> - <literal>buffered</literal>, which is the default, decoding will stream
> - or serialize changes when
> <varname>logical_decoding_work_mem</varname>
> - is reached.
> + <literal>buffered</literal>, decoding will stream or serialize changes
> + when <varname>logical_decoding_work_mem</varname> is
> reached.
> </para>
>
> 2a.
> "it allows" --> "logical_replication_mode allows"
>
> 2b.
> "decoding" --> "the decoding"
Changed.
> ~~~
>
> 3.
> + <para>
> + On the subscriber side, if <literal>streaming</literal> option is set
> + to <literal>parallel</literal>, this parameter also allows the leader
> + apply worker to send changes to the shared memory queue or to
> serialize
> + changes. When set to <literal>buffered</literal>, the leader sends
> + changes to parallel apply workers via shared memory queue. When
> set to
> + <literal>immediate</literal>, the leader serializes all changes to
> + files and notifies the parallel apply workers to read and apply them at
> + the end of the transaction.
> + </para>
>
> "this parameter also allows" --> "logical_replication_mode also allows"
Changed.
> ~~~
>
> 4.
> <para>
> This parameter is intended to be used to test logical decoding and
> replication of large transactions for which otherwise we need to
> generate the changes till
> <varname>logical_decoding_work_mem</varname>
> - is reached.
> + is reached. Moreover, this can also be used to test the transmission of
> + changes between the leader and parallel apply workers.
> </para>
>
> "Moreover, this can also" --> "It can also"
>
> I am wondering would this sentence be better put at the top of the GUC
> description. So then the first paragraph becomes like this:
>
>
> SUGGESTION (I've also added another sentence "The effect of...")
>
> The allowed values are buffered and immediate. The default is buffered. This
> parameter is intended to be used to test logical decoding and replication of large
> transactions for which otherwise we need to generate the changes till
> logical_decoding_work_mem is reached. It can also be used to test the
> transmission of changes between the leader and parallel apply workers. The
> effect of logical_replication_mode is different for the publisher and
> subscriber:
>
> On the publisher side...
>
> On the subscriber side...
I think your suggestion makes sense, so changed as suggested.
> ======
> .../replication/logical/applyparallelworker.c
>
> 5.
> + /*
> + * In immeidate mode, directly return false so that we can switch to
> + * PARTIAL_SERIALIZE mode and serialize remaining changes to files.
> + */
> + if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE) return
> + false;
>
> Typo "immediate"
>
> Also, I felt "directly" is not needed. "return false" and "directly return false" is the
> same.
>
> SUGGESTION
> Using ‘immediate’ mode returns false to cause a switch to PARTIAL_SERIALIZE
> mode so that the remaining changes will be serialized.
Changed.
> ======
> src/backend/utils/misc/guc_tables.c
>
> 6.
> {
> {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
> - gettext_noop("Allows streaming or serializing each change in logical
> decoding."),
> - NULL,
> + gettext_noop("Controls the behavior of logical replication publisher
> and subscriber"),
> + gettext_noop("If set to immediate, on the publisher side, it "
> + "allows streaming or serializing each change in "
> + "logical decoding. On the subscriber side, in "
> + "parallel streaming mode, it allows the leader apply "
> + "worker to serialize changes to files and notifies "
> + "the parallel apply workers to read and apply them at "
> + "the end of the transaction."),
> GUC_NOT_IN_SAMPLE
> },
>
> 6a. short description
>
> User PoV behaviour should be the same. Instead, maybe say "controls the
> internal behavior" or something like that?
Changed to "internal behavior xxx"
> ~
>
> 6b. long description
>
> IMO the long description shouldn’t mention ‘immediate’ mode first as it does.
>
> BEFORE
> If set to immediate, on the publisher side, ...
>
> AFTER
> On the publisher side, ...
Changed.
Attach the new version patch set.
The 0001 patch is the same as the v88-0001 posted by Amit[1],
attach it here to make cfbot happy.
[1] https://www.postgresql.org/message-id/CAA4eK1JpWoaB63YULpQa1KDw_zBW-QoRMuNxuiP1KafPJzuVuw%40mail.gma...
Best Regards,
Hou zj
Attachments:
[application/octet-stream] v88-0001-Rename-GUC-logical_decoding_mode-to-logical_repl.patch (10.9K, ../../OS0PR01MB57164C52100F6B68D2E3874194CE9@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v88-0001-Rename-GUC-logical_decoding_mode-to-logical_repl.patch)
download | inline diff:
From bc9691d5be9bf37fd546d8e6567df0869502dd97 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 20 Jan 2023 14:39:38 +0800
Subject: [PATCH v88 1/2] Rename GUC logical_decoding_mode to
logical_replication_mode.
Rename the developer option 'logical_decoding_mode' to the more flexible
name 'logical_replication_mode' because doing so will make it easier to
extend this option in the future to help test other areas of logical
replication.
Currently, it is used on the publisher side to allow streaming or
serializing each change in logical decoding. In the upcoming patch, we are
planning to use it on the subscriber. On the subscriber, it will allow
serializing the changes to file and notifies the parallel apply workers to
read and apply them at the end of the transaction.
We have discussed having this parameter as a subscription option but
exposing a parameter that is primarily used for testing/debugging to users
didn't seem advisable and there is no other such parameter. The other
option we have discussed is to have a separate GUC for subscriber-side
testing but it appears that for the current testing existing parameter is
sufficient and avoids adding another GUC.
Author: Hou Zhijie
Reviewed-by: Pater Smith, Kuroda Hayato, Amit Kapila
Discussion: https://postgr.es/m/CAD21AoAy2c=Mx=FTCs+EwUsf2kQL5MmU3N18X84k0EmCXntK4g@mail.gmail.com
Discussion: https://postgr.es/m/CAA4eK1+wyN6zpaHUkCLorEWNx75MG0xhMwcFhvjqm2KURZEAGw@mail.gmail.com
---
doc/src/sgml/config.sgml | 8 ++++----
src/backend/replication/logical/reorderbuffer.c | 14 +++++++-------
src/backend/utils/misc/guc_tables.c | 16 ++++++++--------
src/include/replication/reorderbuffer.h | 11 ++++++-----
src/test/subscription/t/016_stream_subxact.pl | 2 +-
.../subscription/t/018_stream_subxact_abort.pl | 2 +-
.../t/019_stream_subxact_ddl_abort.pl | 2 +-
src/test/subscription/t/023_twophase_stream.pl | 2 +-
src/tools/pgindent/typedefs.list | 2 +-
9 files changed, 30 insertions(+), 29 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index f985afc009..1cf53c74ea 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11693,16 +11693,16 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
- <varlistentry id="guc-logical-decoding-mode" xreflabel="logical_decoding_mode">
- <term><varname>logical_decoding_mode</varname> (<type>enum</type>)
+ <varlistentry id="guc-logical-replication-mode" xreflabel="logical_replication_mode">
+ <term><varname>logical_replication_mode</varname> (<type>enum</type>)
<indexterm>
- <primary><varname>logical_decoding_mode</varname> configuration parameter</primary>
+ <primary><varname>logical_replication_mode</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Allows streaming or serializing changes immediately in logical decoding.
- The allowed values of <varname>logical_decoding_mode</varname> are
+ The allowed values of <varname>logical_replication_mode</varname> are
<literal>buffered</literal> and <literal>immediate</literal>. When set
to <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 54ee824e6c..efe057b4de 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -210,7 +210,7 @@ int logical_decoding_work_mem;
static const Size max_changes_in_memory = 4096; /* XXX for restore only */
/* GUC variable */
-int logical_decoding_mode = LOGICAL_DECODING_MODE_BUFFERED;
+int logical_replication_mode = LOGICAL_REP_MODE_BUFFERED;
/* ---------------------------------------
* primary reorderbuffer support routines
@@ -3552,8 +3552,8 @@ ReorderBufferLargestStreamableTopTXN(ReorderBuffer *rb)
* pick the largest (sub)transaction at-a-time to evict and spill its changes to
* disk or send to the output plugin until we reach under the memory limit.
*
- * If logical_decoding_mode is set to "immediate", stream or serialize the changes
- * immediately.
+ * If logical_replication_mode is set to "immediate", stream or serialize the
+ * changes immediately.
*
* XXX At this point we select the transactions until we reach under the memory
* limit, but we might also adapt a more elaborate eviction strategy - for example
@@ -3566,15 +3566,15 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
ReorderBufferTXN *txn;
/*
- * Bail out if logical_decoding_mode is buffered and we haven't exceeded
+ * Bail out if logical_replication_mode is buffered and we haven't exceeded
* the memory limit.
*/
- if (logical_decoding_mode == LOGICAL_DECODING_MODE_BUFFERED &&
+ if (logical_replication_mode == LOGICAL_REP_MODE_BUFFERED &&
rb->size < logical_decoding_work_mem * 1024L)
return;
/*
- * If logical_decoding_mode is immediate, loop until there's no change.
+ * If logical_replication_mode is immediate, loop until there's no change.
* Otherwise, loop until we reach under the memory limit. One might think
* that just by evicting the largest (sub)transaction we will come under
* the memory limit based on assumption that the selected transaction is
@@ -3584,7 +3584,7 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
* change.
*/
while (rb->size >= logical_decoding_work_mem * 1024L ||
- (logical_decoding_mode == LOGICAL_DECODING_MODE_IMMEDIATE &&
+ (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE &&
rb->size > 0))
{
/*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 4ac808ed22..c5a95f5dcc 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -395,9 +395,9 @@ static const struct config_enum_entry ssl_protocol_versions_info[] = {
{NULL, 0, false}
};
-static const struct config_enum_entry logical_decoding_mode_options[] = {
- {"buffered", LOGICAL_DECODING_MODE_BUFFERED, false},
- {"immediate", LOGICAL_DECODING_MODE_IMMEDIATE, false},
+static const struct config_enum_entry logical_replication_mode_options[] = {
+ {"buffered", LOGICAL_REP_MODE_BUFFERED, false},
+ {"immediate", LOGICAL_REP_MODE_IMMEDIATE, false},
{NULL, 0, false}
};
@@ -4919,13 +4919,13 @@ struct config_enum ConfigureNamesEnum[] =
},
{
- {"logical_decoding_mode", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Allows streaming or serializing each change in logical decoding."),
- NULL,
+ {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
+ gettext_noop("Controls when to replicate each change."),
+ gettext_noop("On the publisher, it allows streaming or serializing each change in logical decoding."),
GUC_NOT_IN_SAMPLE
},
- &logical_decoding_mode,
- LOGICAL_DECODING_MODE_BUFFERED, logical_decoding_mode_options,
+ &logical_replication_mode,
+ LOGICAL_REP_MODE_BUFFERED, logical_replication_mode_options,
NULL, NULL, NULL
},
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index f6c4dd75db..e5db041df1 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -17,15 +17,16 @@
#include "utils/snapshot.h"
#include "utils/timestamp.h"
+/* GUC variables */
extern PGDLLIMPORT int logical_decoding_work_mem;
-extern PGDLLIMPORT int logical_decoding_mode;
+extern PGDLLIMPORT int logical_replication_mode;
-/* possible values for logical_decoding_mode */
+/* possible values for logical_replication_mode */
typedef enum
{
- LOGICAL_DECODING_MODE_BUFFERED,
- LOGICAL_DECODING_MODE_IMMEDIATE
-} LogicalDecodingMode;
+ LOGICAL_REP_MODE_BUFFERED,
+ LOGICAL_REP_MODE_IMMEDIATE
+} LogicalRepMode;
/* an individual tuple, stored in one chunk of memory */
typedef struct ReorderBufferTupleBuf
diff --git a/src/test/subscription/t/016_stream_subxact.pl b/src/test/subscription/t/016_stream_subxact.pl
index 2f0148c3a8..d830f26e06 100644
--- a/src/test/subscription/t/016_stream_subxact.pl
+++ b/src/test/subscription/t/016_stream_subxact.pl
@@ -79,7 +79,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index dce14b150a..814daf4d2f 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -130,7 +130,7 @@ sub test_streaming
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
index b30223de51..d0e556c8b8 100644
--- a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
+++ b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl
@@ -16,7 +16,7 @@ use Test::More;
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf',
- 'logical_decoding_mode = immediate');
+ 'logical_replication_mode = immediate');
$node_publisher->start;
# Create subscriber node
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 75ca83765e..497245a209 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -301,7 +301,7 @@ $node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf(
'postgresql.conf', qq(
max_prepared_transactions = 10
-logical_decoding_mode = immediate
+logical_replication_mode = immediate
));
$node_publisher->start;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 51484ca7e2..07fbb7ccf6 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1458,7 +1458,6 @@ LogicalDecodeStreamStopCB
LogicalDecodeStreamTruncateCB
LogicalDecodeTruncateCB
LogicalDecodingContext
-LogicalDecodingMode
LogicalErrorCallbackState
LogicalOutputPluginInit
LogicalOutputPluginWriterPrepareWrite
@@ -1468,6 +1467,7 @@ LogicalRepBeginData
LogicalRepCommitData
LogicalRepCommitPreparedTxnData
LogicalRepCtxStruct
+LogicalRepMode
LogicalRepMsgType
LogicalRepPartMapEntry
LogicalRepPreparedTxnData
--
2.28.0.windows.1
[application/octet-stream] v88-0002-Extend-the-logical_replication_mode-to-test-the-.patch (14.3K, ../../OS0PR01MB57164C52100F6B68D2E3874194CE9@OS0PR01MB5716.jpnprd01.prod.outlook.com/3-v88-0002-Extend-the-logical_replication_mode-to-test-the-.patch)
download | inline diff:
From 047ff210b77a253658222f58e8b8c8a83419f1c6 Mon Sep 17 00:00:00 2001
From: Hou <[email protected]>
Date: Wed, 25 Jan 2023 22:00:31 +0800
Subject: [PATCH v88 2/2] Extend the logical_replication_mode to test the
stream parallel mode
Give additional functionality to the existing developer option
'logical_replication_mode' to help test parallel apply of large
transactions on the subscriber.
When set to 'buffered', the leader sends changes to parallel apply workers via
shared memory queue. When set to 'immediate', the leader serializes all changes
to files and notifies the parallel apply workers to read and apply them at the
end of the transaction.
This helps in adding tests to cover the serialization code path in parallel
streaming mode.
---
doc/src/sgml/config.sgml | 36 +++++++----
.../replication/logical/applyparallelworker.c | 16 +++--
src/backend/utils/misc/guc_tables.c | 9 ++-
src/test/subscription/t/015_stream.pl | 27 ++++++++
.../t/018_stream_subxact_abort.pl | 61 ++++++++++++++++++-
.../subscription/t/023_twophase_stream.pl | 45 +++++++++++++-
6 files changed, 174 insertions(+), 20 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 1cf53c74ea..c00ec90b56 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11701,22 +11701,36 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</term>
<listitem>
<para>
- Allows streaming or serializing changes immediately in logical decoding.
- The allowed values of <varname>logical_replication_mode</varname> are
- <literal>buffered</literal> and <literal>immediate</literal>. When set
- to <literal>immediate</literal>, stream each change if
+ The allowed values are <literal>buffered</literal> and
+ <literal>immediate</literal>. The default is <literal>buffered</literal>.
+ This parameter is intended to be used to test logical decoding and
+ replication of large transactions for which otherwise we need to generate
+ the changes till logical_decoding_work_mem is reached. It can also be
+ used to test the transmission of changes between the leader and parallel
+ apply workers. The effect of <varname>logical_replication_mode</varname>
+ is different for the publisher and subscriber:
+ </para>
+
+ <para>
+ On the publisher side, <varname>logical_replication_mode</varname> allows
+ allows streaming or serializing changes immediately in logical decoding.
+ When set to <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
<link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link>)
is enabled, otherwise, serialize each change. When set to
- <literal>buffered</literal>, which is the default, decoding will stream
- or serialize changes when <varname>logical_decoding_work_mem</varname>
- is reached.
+ <literal>buffered</literal>, the decoding will stream or serialize
+ changes when <varname>logical_decoding_work_mem</varname> is reached.
</para>
+
<para>
- This parameter is intended to be used to test logical decoding and
- replication of large transactions for which otherwise we need to
- generate the changes till <varname>logical_decoding_work_mem</varname>
- is reached.
+ On the subscriber side, if <literal>streaming</literal> option is set to
+ <literal>parallel</literal>, <varname>logical_replication_mode</varname>
+ also allows the leader apply worker to send changes to the shared memory
+ queue or to serialize changes. When set to <literal>buffered</literal>,
+ the leader sends changes to parallel apply workers via shared memory
+ queue. When set to <literal>immediate</literal>, the leader serializes
+ all changes to files and notifies the parallel apply workers to read and
+ apply them at the end of the transaction.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3579e704fe..f0b1ec2df3 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -1149,6 +1149,13 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ /*
+ * Using 'immediate' mode returns false to cause a switch to
+ * PARTIAL_SERIALIZE mode so that the remaining changes will be serialized.
+ */
+ if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE)
+ return false;
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
@@ -1187,12 +1194,7 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
startTime = GetCurrentTimestamp();
else if (TimestampDifferenceExceeds(startTime, GetCurrentTimestamp(),
SHM_SEND_TIMEOUT_MS))
- {
- ereport(LOG,
- (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
- winfo->shared->xid)));
return false;
- }
}
}
@@ -1206,6 +1208,10 @@ void
pa_switch_to_partial_serialize(ParallelApplyWorkerInfo *winfo,
bool stream_locked)
{
+ ereport(LOG,
+ (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
+ winfo->shared->xid)));
+
/*
* The parallel apply worker could be stuck for some reason (say waiting
* on some lock by other backend), so stop trying to send data directly to
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index c5a95f5dcc..2e352d50ba 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -4920,8 +4920,13 @@ struct config_enum ConfigureNamesEnum[] =
{
{"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Controls when to replicate each change."),
- gettext_noop("On the publisher, it allows streaming or serializing each change in logical decoding."),
+ gettext_noop("Controls the internal behavior of logical replication publisher and subscriber"),
+ gettext_noop("On the publisher, it allows streaming or "
+ "serializing each change in logical decoding. On the "
+ "subscriber, in parallel streaming mode, it allows "
+ "the leader apply worker to serialize changes to "
+ "files and notifies the parallel apply workers to "
+ "read and apply them at the end of the transaction."),
GUC_NOT_IN_SAMPLE
},
&logical_replication_mode,
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8c0a..c591cfea5a 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -312,6 +312,33 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(15000), 'all changes are replayed from file');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index 814daf4d2f..455fde2a7c 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -143,15 +143,17 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c INT, d INT, e INT)");
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -198,6 +200,63 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0), 'check rollback was reflected on subscriber');
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'check rollback to savepoint was reflected on subscriber');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 497245a209..9f046e13b8 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -319,16 +319,18 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber (columns a and b are compatible with same table name on publisher)
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999)"
);
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication (streaming = on)
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -384,6 +386,47 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'transaction is committed on subscriber');
+
###############################
# check all the cleanup
###############################
--
2.28.0.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-26 03:36 ` Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-30 06:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Hayato Kuroda (Fujitsu) @ 2023-01-26 03:36 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Peter Smith <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
Dear Hou,
Thank you for updating the patch! Followings are comments.
1. config.sgml
```
+ the changes till logical_decoding_work_mem is reached. It can also be
```
I think it should be sandwiched by <varname>.
2. config.sgml
```
+ On the publisher side, <varname>logical_replication_mode</varname> allows
+ allows streaming or serializing changes immediately in logical decoding.
```
Typo "allows allows" -> "allows"
3. test general
You confirmed that the leader started to serialize changes, but did not ensure the endpoint.
IIUC the parallel apply worker exits after applying serialized changes, and it is not tested yet.
Can we add polling the log somewhere?
4. 015_stream.pl
```
+is($result, qq(15000), 'all changes are replayed from file')
```
The statement may be unclear because changes can be also replicated when streaming = on.
How about: "parallel apply worker replayed all changes from file"?
Best Regards,
Hayato Kuroda
FUJITSU LIMITED
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-26 03:36 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
@ 2023-01-30 06:24 ` [email protected] <[email protected]>
2023-01-30 12:57 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: [email protected] @ 2023-01-30 06:24 UTC (permalink / raw)
To: Hayato Kuroda (Fujitsu) <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Peter Smith <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Thursday, January 26, 2023 11:37 AM Kuroda, Hayato/黒田 隼人 <[email protected]> wrote:
>
> Followings are comments.
Thanks for the comments.
> In this test the rollback-prepared seems not to be executed. This is because
> serializations are finished while handling PREPARE message and the final
> state of transaction does not affect that, right? I think it may be helpful
> to add a one line comment.
Yes, but I am slightly unsure if it would be helpful to add this as we only test basic
cases(mainly for code coverage) for partial serialization.
>
> 1. config.sgml
>
> ```
> + the changes till logical_decoding_work_mem is reached. It can also
> be
> ```
>
> I think it should be sandwiched by <varname>.
Added.
>
> 2. config.sgml
>
> ```
> + On the publisher side,
> <varname>logical_replication_mode</varname> allows
> + allows streaming or serializing changes immediately in logical
> decoding.
> ```
>
> Typo "allows allows" -> "allows"
Fixed.
> 3. test general
>
> You confirmed that the leader started to serialize changes, but did not ensure
> the endpoint.
> IIUC the parallel apply worker exits after applying serialized changes, and it is
> not tested yet.
> Can we add polling the log somewhere?
I checked other tests and didn't find some examples where we test the exit of
apply worker or table sync worker. And if the parallel apply worker doesn't stop in
this case, we will fail anyway when reusing this worker to handle the next
transaction because the queue is broken. So, I prefer to keep the tests short.
> 4. 015_stream.pl
>
> ```
> +is($result, qq(15000), 'all changes are replayed from file')
> ```
>
> The statement may be unclear because changes can be also replicated when
> streaming = on.
> How about: "parallel apply worker replayed all changes from file"?
Changed.
Best regards,
Hou zj
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-26 03:36 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-30 06:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-30 12:57 ` Hayato Kuroda (Fujitsu) <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: Hayato Kuroda (Fujitsu) @ 2023-01-30 12:57 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Peter Smith <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
Dear Hou,
Thank you for updating the patch!
I checked your replies and new patch, and it seems good.
Currently I have no comments
Best Regards,
Hayato Kuroda
FUJITSU LIMITED
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-30 00:10 ` Peter Smith <[email protected]>
2023-01-30 06:11 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Peter Smith @ 2023-01-30 00:10 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
Patch v88-0001 LGTM.
Below are just some minor review comments about the commit message.
======
Commit message
1.
We have discussed having this parameter as a subscription option but
exposing a parameter that is primarily used for testing/debugging to users
didn't seem advisable and there is no other such parameter. The other
option we have discussed is to have a separate GUC for subscriber-side
testing but it appears that for the current testing existing parameter is
sufficient and avoids adding another GUC.
SUGGESTION
We discussed exposing this parameter as a subscription option, but it
did not seem advisable since it is primarily used for
testing/debugging and there is no other such developer option.
We also discussed having separate GUCs for publisher/subscriber-side,
but for current testing/debugging requirements, one GUC is sufficient.
~~
2.
Reviewed-by: Pater Smith, Kuroda Hayato, Amit Kapila
"Pater" --> "Peter"
------
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-30 00:10 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-30 06:11 ` Amit Kapila <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: Amit Kapila @ 2023-01-30 06:11 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: [email protected] <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Mon, Jan 30, 2023 at 5:40 AM Peter Smith <[email protected]> wrote:
>
> Patch v88-0001 LGTM.
>
Pushed.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-30 04:12 ` Peter Smith <[email protected]>
2023-01-30 06:23 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Peter Smith @ 2023-01-30 04:12 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
Here are my review comments for v88-0002.
======
General
1.
The test cases are checking the log content but they are not checking
for debug logs or untranslated elogs -- they are expecting a normal
ereport LOG that might be translated. I’m not sure if that is OK, or
if it is a potential problem.
======
doc/src/sgml/config.sgml
2.
On the publisher side, logical_replication_mode allows allows
streaming or serializing changes immediately in logical decoding. When
set to immediate, stream each change if streaming option (see optional
parameters set by CREATE SUBSCRIPTION) is enabled, otherwise,
serialize each change. When set to buffered, the decoding will stream
or serialize changes when logical_decoding_work_mem is reached.
2a.
typo "allows allows" (Kuroda-san reported same)
2b.
"if streaming option" --> "if the streaming option"
~~~
3.
On the subscriber side, if streaming option is set to parallel,
logical_replication_mode also allows the leader apply worker to send
changes to the shared memory queue or to serialize changes.
SUGGESTION
On the subscriber side, if the streaming option is set to parallel,
logical_replication_mode can be used to direct the leader apply worker
to send changes to the shared memory queue or to serialize changes.
======
src/backend/utils/misc/guc_tables.c
4.
{
{"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Controls when to replicate each change."),
- gettext_noop("On the publisher, it allows streaming or serializing
each change in logical decoding."),
+ gettext_noop("Controls the internal behavior of logical replication
publisher and subscriber"),
+ gettext_noop("On the publisher, it allows streaming or "
+ "serializing each change in logical decoding. On the "
+ "subscriber, in parallel streaming mode, it allows "
+ "the leader apply worker to serialize changes to "
+ "files and notifies the parallel apply workers to "
+ "read and apply them at the end of the transaction."),
GUC_NOT_IN_SAMPLE
},
Suggest re-wording the long description (subscriber part) to be more
like the documentation text.
BEFORE
On the subscriber, in parallel streaming mode, it allows the leader
apply worker to serialize changes to files and notifies the parallel
apply workers to read and apply them at the end of the transaction.
SUGGESTION
On the subscriber, if the streaming option is set to parallel, it
directs the leader apply worker to send changes to the shared memory
queue or to serialize changes and apply them at the end of the
transaction.
------
Kind Regards,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-30 04:12 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-30 06:23 ` [email protected] <[email protected]>
2023-01-30 14:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: [email protected] @ 2023-01-30 06:23 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Monday, January 30, 2023 12:13 PM Peter Smith <[email protected]> wrote:
>
> Here are my review comments for v88-0002.
Thanks for your comments.
>
> ======
> General
>
> 1.
> The test cases are checking the log content but they are not checking for
> debug logs or untranslated elogs -- they are expecting a normal ereport LOG
> that might be translated. I’m not sure if that is OK, or if it is a potential problem.
We have tests that check the ereport ERROR and ereport WARNING message(by
search for the ERROR or WARNING keyword for all the tap tests), so I think
checking the LOG should be fine.
> ======
> doc/src/sgml/config.sgml
>
> 2.
> On the publisher side, logical_replication_mode allows allows streaming or
> serializing changes immediately in logical decoding. When set to immediate,
> stream each change if streaming option (see optional parameters set by
> CREATE SUBSCRIPTION) is enabled, otherwise, serialize each change. When set
> to buffered, the decoding will stream or serialize changes when
> logical_decoding_work_mem is reached.
>
> 2a.
> typo "allows allows" (Kuroda-san reported same)
>
> 2b.
> "if streaming option" --> "if the streaming option"
Changed.
> ~~~
>
> 3.
> On the subscriber side, if streaming option is set to parallel,
> logical_replication_mode also allows the leader apply worker to send changes
> to the shared memory queue or to serialize changes.
>
> SUGGESTION
> On the subscriber side, if the streaming option is set to parallel,
> logical_replication_mode can be used to direct the leader apply worker to
> send changes to the shared memory queue or to serialize changes.
Changed.
> ======
> src/backend/utils/misc/guc_tables.c
>
> 4.
> {
> {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
> - gettext_noop("Controls when to replicate each change."),
> - gettext_noop("On the publisher, it allows streaming or serializing each
> change in logical decoding."),
> + gettext_noop("Controls the internal behavior of logical replication
> publisher and subscriber"),
> + gettext_noop("On the publisher, it allows streaming or "
> + "serializing each change in logical decoding. On the "
> + "subscriber, in parallel streaming mode, it allows "
> + "the leader apply worker to serialize changes to "
> + "files and notifies the parallel apply workers to "
> + "read and apply them at the end of the transaction."),
> GUC_NOT_IN_SAMPLE
> },
> Suggest re-wording the long description (subscriber part) to be more like the
> documentation text.
>
> BEFORE
> On the subscriber, in parallel streaming mode, it allows the leader apply worker
> to serialize changes to files and notifies the parallel apply workers to read and
> apply them at the end of the transaction.
>
> SUGGESTION
> On the subscriber, if the streaming option is set to parallel, it directs the leader
> apply worker to send changes to the shared memory queue or to serialize
> changes and apply them at the end of the transaction.
>
Changed.
Attach the new version patch which addressed all comments so far (the v88-0001
has been committed, so we only have one remaining patch this time).
Best Regards,
Hou zj
Attachments:
[application/octet-stream] v89-0001-Extend-the-logical_replication_mode-to-test-the-.patch (14.3K, ../../OS0PR01MB5716D08CD8A914AF59F4120894D39@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v89-0001-Extend-the-logical_replication_mode-to-test-the-.patch)
download | inline diff:
From 4d0c70767c6a8099333a4aaf8734dfd614d64a9c Mon Sep 17 00:00:00 2001
From: Hou <[email protected]>
Date: Wed, 25 Jan 2023 22:00:31 +0800
Subject: [PATCH v89] Extend the logical_replication_mode to test the stream
parallel mode
Give additional functionality to the existing developer option
'logical_replication_mode' to help test parallel apply of large
transactions on the subscriber.
When set to 'buffered', the leader sends changes to parallel apply workers via
shared memory queue. When set to 'immediate', the leader serializes all changes
to files and notifies the parallel apply workers to read and apply them at the
end of the transaction.
This helps in adding tests to cover the serialization code path in parallel
streaming mode.
---
doc/src/sgml/config.sgml | 38 ++++++++++----
.../replication/logical/applyparallelworker.c | 16 ++++--
src/backend/utils/misc/guc_tables.c | 9 +++-
src/test/subscription/t/015_stream.pl | 27 ++++++++++
.../subscription/t/018_stream_subxact_abort.pl | 61 +++++++++++++++++++++-
src/test/subscription/t/023_twophase_stream.pl | 45 +++++++++++++++-
6 files changed, 176 insertions(+), 20 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 1cf53c7..600eade 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11701,22 +11701,38 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</term>
<listitem>
<para>
- Allows streaming or serializing changes immediately in logical decoding.
- The allowed values of <varname>logical_replication_mode</varname> are
- <literal>buffered</literal> and <literal>immediate</literal>. When set
- to <literal>immediate</literal>, stream each change if
+ The allowed values are <literal>buffered</literal> and
+ <literal>immediate</literal>. The default is <literal>buffered</literal>.
+ This parameter is intended to be used to test logical decoding and
+ replication of large transactions for which otherwise we need to generate
+ the changes till <varname>logical_decoding_work_mem</varname> is
+ reached. It can also be used to test the transmission of changes between
+ the leader and parallel apply workers. The effect of
+ <varname>logical_replication_mode</varname> is different for the
+ publisher and subscriber:
+ </para>
+
+ <para>
+ On the publisher side, <varname>logical_replication_mode</varname>
+ allows streaming or serializing changes immediately in logical decoding.
+ When set to <literal>immediate</literal>, stream each change if
<literal>streaming</literal> option (see optional parameters set by
<link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link>)
is enabled, otherwise, serialize each change. When set to
- <literal>buffered</literal>, which is the default, decoding will stream
- or serialize changes when <varname>logical_decoding_work_mem</varname>
- is reached.
+ <literal>buffered</literal>, the decoding will stream or serialize
+ changes when <varname>logical_decoding_work_mem</varname> is reached.
</para>
+
<para>
- This parameter is intended to be used to test logical decoding and
- replication of large transactions for which otherwise we need to
- generate the changes till <varname>logical_decoding_work_mem</varname>
- is reached.
+ On the subscriber side, if the <literal>streaming</literal> option is set to
+ <literal>parallel</literal>, <varname>logical_replication_mode</varname>
+ can be used to direct the leader apply worker to send changes to the
+ shared memory queue or to serialize changes. When set to
+ <literal>buffered</literal>, the leader sends changes to parallel apply
+ workers via shared memory queue. When set to
+ <literal>immediate</literal>, the leader serializes all changes to files
+ and notifies the parallel apply workers to read and apply them at the
+ end of the transaction.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3579e70..f0b1ec2 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -1149,6 +1149,13 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ /*
+ * Using 'immediate' mode returns false to cause a switch to
+ * PARTIAL_SERIALIZE mode so that the remaining changes will be serialized.
+ */
+ if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE)
+ return false;
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
@@ -1187,12 +1194,7 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
startTime = GetCurrentTimestamp();
else if (TimestampDifferenceExceeds(startTime, GetCurrentTimestamp(),
SHM_SEND_TIMEOUT_MS))
- {
- ereport(LOG,
- (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
- winfo->shared->xid)));
return false;
- }
}
}
@@ -1206,6 +1208,10 @@ void
pa_switch_to_partial_serialize(ParallelApplyWorkerInfo *winfo,
bool stream_locked)
{
+ ereport(LOG,
+ (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
+ winfo->shared->xid)));
+
/*
* The parallel apply worker could be stuck for some reason (say waiting
* on some lock by other backend), so stop trying to send data directly to
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index c5a95f5..a826640 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -4920,8 +4920,13 @@ struct config_enum ConfigureNamesEnum[] =
{
{"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Controls when to replicate each change."),
- gettext_noop("On the publisher, it allows streaming or serializing each change in logical decoding."),
+ gettext_noop("Controls the internal behavior of logical replication publisher and subscriber"),
+ gettext_noop("On the publisher, it allows streaming or "
+ "serializing each change in logical decoding. On the "
+ "subscriber, if the streaming option is set to "
+ "parallel, it directs the leader apply worker to send "
+ "changes to the shared memory queue or to serialize "
+ "changes and apply them at the end of the transaction."),
GUC_NOT_IN_SAMPLE
},
&logical_replication_mode,
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8..e565ab8 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -312,6 +312,33 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(15000), 'parallel apply worker replayed all changes from file');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index 814daf4..455fde2 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -143,15 +143,17 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c INT, d INT, e INT)");
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -198,6 +200,63 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0), 'check rollback was reflected on subscriber');
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'check rollback to savepoint was reflected on subscriber');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 497245a..9f046e1 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -319,16 +319,18 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber (columns a and b are compatible with same table name on publisher)
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999)"
);
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication (streaming = on)
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -384,6 +386,47 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'transaction is committed on subscriber');
+
###############################
# check all the cleanup
###############################
--
2.7.2.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-30 04:12 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-30 06:23 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-30 14:19 ` Masahiko Sawada <[email protected]>
2023-01-31 03:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Masahiko Sawada @ 2023-01-30 14:19 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Peter Smith <[email protected]>; Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Mon, Jan 30, 2023 at 3:23 PM [email protected]
<[email protected]> wrote:
>
> On Monday, January 30, 2023 12:13 PM Peter Smith <[email protected]> wrote:
> >
> > Here are my review comments for v88-0002.
>
> Thanks for your comments.
>
> >
> > ======
> > General
> >
> > 1.
> > The test cases are checking the log content but they are not checking for
> > debug logs or untranslated elogs -- they are expecting a normal ereport LOG
> > that might be translated. I’m not sure if that is OK, or if it is a potential problem.
>
> We have tests that check the ereport ERROR and ereport WARNING message(by
> search for the ERROR or WARNING keyword for all the tap tests), so I think
> checking the LOG should be fine.
>
> > ======
> > doc/src/sgml/config.sgml
> >
> > 2.
> > On the publisher side, logical_replication_mode allows allows streaming or
> > serializing changes immediately in logical decoding. When set to immediate,
> > stream each change if streaming option (see optional parameters set by
> > CREATE SUBSCRIPTION) is enabled, otherwise, serialize each change. When set
> > to buffered, the decoding will stream or serialize changes when
> > logical_decoding_work_mem is reached.
> >
> > 2a.
> > typo "allows allows" (Kuroda-san reported same)
> >
> > 2b.
> > "if streaming option" --> "if the streaming option"
>
> Changed.
>
> > ~~~
> >
> > 3.
> > On the subscriber side, if streaming option is set to parallel,
> > logical_replication_mode also allows the leader apply worker to send changes
> > to the shared memory queue or to serialize changes.
> >
> > SUGGESTION
> > On the subscriber side, if the streaming option is set to parallel,
> > logical_replication_mode can be used to direct the leader apply worker to
> > send changes to the shared memory queue or to serialize changes.
>
> Changed.
>
> > ======
> > src/backend/utils/misc/guc_tables.c
> >
> > 4.
> > {
> > {"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
> > - gettext_noop("Controls when to replicate each change."),
> > - gettext_noop("On the publisher, it allows streaming or serializing each
> > change in logical decoding."),
> > + gettext_noop("Controls the internal behavior of logical replication
> > publisher and subscriber"),
> > + gettext_noop("On the publisher, it allows streaming or "
> > + "serializing each change in logical decoding. On the "
> > + "subscriber, in parallel streaming mode, it allows "
> > + "the leader apply worker to serialize changes to "
> > + "files and notifies the parallel apply workers to "
> > + "read and apply them at the end of the transaction."),
> > GUC_NOT_IN_SAMPLE
> > },
> > Suggest re-wording the long description (subscriber part) to be more like the
> > documentation text.
> >
> > BEFORE
> > On the subscriber, in parallel streaming mode, it allows the leader apply worker
> > to serialize changes to files and notifies the parallel apply workers to read and
> > apply them at the end of the transaction.
> >
> > SUGGESTION
> > On the subscriber, if the streaming option is set to parallel, it directs the leader
> > apply worker to send changes to the shared memory queue or to serialize
> > changes and apply them at the end of the transaction.
> >
>
> Changed.
>
> Attach the new version patch which addressed all comments so far (the v88-0001
> has been committed, so we only have one remaining patch this time).
>
I have one comment on v89 patch:
+ /*
+ * Using 'immediate' mode returns false to cause a switch to
+ * PARTIAL_SERIALIZE mode so that the remaining changes will
be serialized.
+ */
+ if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE)
+ return false;
+
Probably we might want to add unlikely() here since we could pass
through this path very frequently?
The rest looks good to me.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-30 04:12 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-30 06:23 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-30 14:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-01-31 03:34 ` [email protected] <[email protected]>
2023-01-31 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: [email protected] @ 2023-01-31 03:34 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: Peter Smith <[email protected]>; Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Monday, January 30, 2023 10:20 PM Masahiko Sawada <[email protected]> wrote:
>
>
> I have one comment on v89 patch:
>
> + /*
> + * Using 'immediate' mode returns false to cause a switch to
> + * PARTIAL_SERIALIZE mode so that the remaining changes will
> be serialized.
> + */
> + if (logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE)
> + return false;
> +
>
> Probably we might want to add unlikely() here since we could pass through this
> path very frequently?
I think your comment makes sense, thanks.
I updated the patch for the same.
Best Regards,
Hou zj
Attachments:
[application/octet-stream] v90-0001-Extend-the-logical_replication_mode-to-test-the-.patch (14.3K, ../../OS0PR01MB571621A51D40CA3DE45E6E0694D09@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v90-0001-Extend-the-logical_replication_mode-to-test-the-.patch)
download | inline diff:
From dc73a30abb863d8fcb10e2be1afa0c28b488db9e Mon Sep 17 00:00:00 2001
From: Hou <[email protected]>
Date: Wed, 25 Jan 2023 22:00:31 +0800
Subject: [PATCH v90] Extend the logical_replication_mode to test the stream
parallel mode
Give additional functionality to the existing developer option
'logical_replication_mode' to help test parallel apply of large
transactions on the subscriber.
When set to 'buffered', the leader sends changes to parallel apply workers via
shared memory queue. When set to 'immediate', the leader serializes all changes
to files and notifies the parallel apply workers to read and apply them at the
end of the transaction.
This helps in adding tests to cover the serialization code path in parallel
streaming mode.
---
doc/src/sgml/config.sgml | 38 ++++++++++----
.../replication/logical/applyparallelworker.c | 16 ++++--
src/backend/utils/misc/guc_tables.c | 9 +++-
src/test/subscription/t/015_stream.pl | 27 ++++++++++
.../subscription/t/018_stream_subxact_abort.pl | 61 +++++++++++++++++++++-
src/test/subscription/t/023_twophase_stream.pl | 45 +++++++++++++++-
6 files changed, 176 insertions(+), 20 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 1cf53c7..e0bbad8 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11701,22 +11701,38 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</term>
<listitem>
<para>
- Allows streaming or serializing changes immediately in logical decoding.
- The allowed values of <varname>logical_replication_mode</varname> are
- <literal>buffered</literal> and <literal>immediate</literal>. When set
- to <literal>immediate</literal>, stream each change if
+ The allowed values are <literal>buffered</literal> and
+ <literal>immediate</literal>. The default is <literal>buffered</literal>.
+ This parameter is intended to be used to test logical decoding and
+ replication of large transactions for which otherwise we need to generate
+ the changes till <varname>logical_decoding_work_mem</varname> is
+ reached. It can also be used to test the transmission of changes between
+ the leader and parallel apply workers. The effect of
+ <varname>logical_replication_mode</varname> is different for the
+ publisher and subscriber:
+ </para>
+
+ <para>
+ On the publisher side, <varname>logical_replication_mode</varname>
+ allows streaming or serializing changes immediately in logical decoding.
+ When set to <literal>immediate</literal>, stream each change if the
<literal>streaming</literal> option (see optional parameters set by
<link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link>)
is enabled, otherwise, serialize each change. When set to
- <literal>buffered</literal>, which is the default, decoding will stream
- or serialize changes when <varname>logical_decoding_work_mem</varname>
- is reached.
+ <literal>buffered</literal>, the decoding will stream or serialize
+ changes when <varname>logical_decoding_work_mem</varname> is reached.
</para>
+
<para>
- This parameter is intended to be used to test logical decoding and
- replication of large transactions for which otherwise we need to
- generate the changes till <varname>logical_decoding_work_mem</varname>
- is reached.
+ On the subscriber side, if the <literal>streaming</literal> option is set to
+ <literal>parallel</literal>, <varname>logical_replication_mode</varname>
+ can be used to direct the leader apply worker to send changes to the
+ shared memory queue or to serialize changes. When set to
+ <literal>buffered</literal>, the leader sends changes to parallel apply
+ workers via shared memory queue. When set to
+ <literal>immediate</literal>, the leader serializes all changes to files
+ and notifies the parallel apply workers to read and apply them at the
+ end of the transaction.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 3579e70..0ce0313 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -1149,6 +1149,13 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
Assert(!IsTransactionState());
Assert(!winfo->serialize_changes);
+ /*
+ * Using 'immediate' mode returns false to cause a switch to
+ * PARTIAL_SERIALIZE mode so that the remaining changes will be serialized.
+ */
+ if (unlikely(logical_replication_mode == LOGICAL_REP_MODE_IMMEDIATE))
+ return false;
+
/*
* This timeout is a bit arbitrary but testing revealed that it is sufficient
* to send the message unless the parallel apply worker is waiting on some
@@ -1187,12 +1194,7 @@ pa_send_data(ParallelApplyWorkerInfo *winfo, Size nbytes, const void *data)
startTime = GetCurrentTimestamp();
else if (TimestampDifferenceExceeds(startTime, GetCurrentTimestamp(),
SHM_SEND_TIMEOUT_MS))
- {
- ereport(LOG,
- (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
- winfo->shared->xid)));
return false;
- }
}
}
@@ -1206,6 +1208,10 @@ void
pa_switch_to_partial_serialize(ParallelApplyWorkerInfo *winfo,
bool stream_locked)
{
+ ereport(LOG,
+ (errmsg("logical replication apply worker will serialize the remaining changes of remote transaction %u to a file",
+ winfo->shared->xid)));
+
/*
* The parallel apply worker could be stuck for some reason (say waiting
* on some lock by other backend), so stop trying to send data directly to
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index c5a95f5..a826640 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -4920,8 +4920,13 @@ struct config_enum ConfigureNamesEnum[] =
{
{"logical_replication_mode", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Controls when to replicate each change."),
- gettext_noop("On the publisher, it allows streaming or serializing each change in logical decoding."),
+ gettext_noop("Controls the internal behavior of logical replication publisher and subscriber"),
+ gettext_noop("On the publisher, it allows streaming or "
+ "serializing each change in logical decoding. On the "
+ "subscriber, if the streaming option is set to "
+ "parallel, it directs the leader apply worker to send "
+ "changes to the shared memory queue or to serialize "
+ "changes and apply them at the end of the transaction."),
GUC_NOT_IN_SAMPLE
},
&logical_replication_mode,
diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl
index 91e8aa8..e565ab8 100644
--- a/src/test/subscription/t/015_stream.pl
+++ b/src/test/subscription/t/015_stream.pl
@@ -312,6 +312,33 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
is($result, qq(10000), 'data replicated to subscriber after dropping index');
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO test_tab_2 SELECT i FROM generate_series(1, 5000) s(i)");
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(15000), 'parallel apply worker replayed all changes from file');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl
index 814daf4..455fde2 100644
--- a/src/test/subscription/t/018_stream_subxact_abort.pl
+++ b/src/test/subscription/t/018_stream_subxact_abort.pl
@@ -143,15 +143,17 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c INT, d INT, e INT)");
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -198,6 +200,63 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is aborted on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(0), 'check rollback was reflected on subscriber');
+
+# Serialize the ABORT sub-transaction.
+# Check the subscriber log from now on.
+$offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ SAVEPOINT sp;
+ INSERT INTO test_tab_2 values(1);
+ ROLLBACK TO sp;
+ COMMIT;
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that only sub-transaction is aborted on subscriber.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'check rollback to savepoint was reflected on subscriber');
+
$node_subscriber->stop;
$node_publisher->stop;
diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl
index 497245a..9f046e1 100644
--- a/src/test/subscription/t/023_twophase_stream.pl
+++ b/src/test/subscription/t/023_twophase_stream.pl
@@ -319,16 +319,18 @@ $node_publisher->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b varchar)");
$node_publisher->safe_psql('postgres',
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
+$node_publisher->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup structure on subscriber (columns a and b are compatible with same table name on publisher)
$node_subscriber->safe_psql('postgres',
"CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999)"
);
+$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab_2 (a int)");
# Setup logical replication (streaming = on)
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
- "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
+ "CREATE PUBLICATION tap_pub FOR TABLE test_tab, test_tab_2");
my $appname = 'tap_sub';
@@ -384,6 +386,47 @@ $node_subscriber->safe_psql('postgres', q{SELECT 1});
test_streaming($node_publisher, $node_subscriber, $appname, 1);
+# Test serializing changes to files and notify the parallel apply worker to
+# apply them at the end of transaction.
+$node_subscriber->append_conf('postgresql.conf',
+ 'logical_replication_mode = immediate');
+$node_subscriber->append_conf('postgresql.conf', "log_min_messages = warning");
+$node_subscriber->reload;
+
+# Run a query to make sure that the reload has taken effect.
+$node_subscriber->safe_psql('postgres', q{SELECT 1});
+
+my $offset = -s $node_subscriber->logfile;
+
+$node_publisher->safe_psql(
+ 'postgres', q{
+ BEGIN;
+ INSERT INTO test_tab_2 values(1);
+ PREPARE TRANSACTION 'xact';
+ });
+
+# Ensure that the changes are serialized.
+$node_subscriber->wait_for_log(
+ qr/LOG: ( [A-Z0-9]+:)? logical replication apply worker will serialize the remaining changes of remote transaction \d+ to a file/,
+ $offset);
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is in prepared state on subscriber
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*) FROM pg_prepared_xacts;");
+is($result, qq(1), 'transaction is prepared on subscriber');
+
+# Check that 2PC gets committed on subscriber
+$node_publisher->safe_psql('postgres', "COMMIT PREPARED 'xact';");
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check that transaction is committed on subscriber
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_tab_2");
+is($result, qq(1), 'transaction is committed on subscriber');
+
###############################
# check all the cleanup
###############################
--
2.7.2.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-30 04:12 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-30 06:23 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-30 14:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-31 03:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
@ 2023-01-31 05:40 ` Peter Smith <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: Peter Smith @ 2023-01-31 05:40 UTC (permalink / raw)
To: [email protected] <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; Amit Kapila <[email protected]>; shveta malik <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
Thanks for the updates to address all of my previous review comments.
Patch v90-0001 LGTM.
------
Kind Reagrds,
Peter Smith.
Fujitsu Australia
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-13 02:52 ` shveta malik <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: shveta malik @ 2023-01-13 02:52 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Peter Smith <[email protected]>; [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; shveta malik <[email protected]>
On Thu, Jan 12, 2023 at 4:37 PM Amit Kapila <[email protected]> wrote:
>
>
> But then do you suggest that tomorrow if we allow parallel sync
> workers then we have a separate column leader_sync_pid? I think that
> doesn't sound like a good idea and moreover one can refer to docs for
> clarification.
>
> --
okay, leader_pid is fine I think.
thanks
Shveta
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
@ 2023-01-12 12:34 ` [email protected] <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: [email protected] @ 2023-01-12 12:34 UTC (permalink / raw)
To: Peter Smith <[email protected]>; +Cc: Amit Kapila <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Thursday, January 12, 2023 12:24 PM Peter Smith <[email protected]> wrote:
>
> Hi, here are some review comments for patch v78-0001.
Thanks for your comments.
> ======
>
> General
>
> 1. (terminology)
>
> AFAIK everywhere until now we’ve been referring everywhere
> (docs/comments/code) to the parent apply worker as the "leader apply
> worker". Not the "main apply worker". Not the "apply leader worker".
> Not any other variations...
>
> From this POV I think the worker member "apply_leader_pid" would be better
> named "leader_apply_pid", but I see that this was already committed to
> HEAD differently.
>
> Maybe it is not possible (or you don't want) to change that internal member
> name but IMO at least all the new code and docs should try to be using
> consistent terminology (e.g. leader_apply_XXX) where possible.
>
> ======
>
> Commit message
>
> 2.
>
> main_worker_pid is Process ID of the leader apply worker, if this process is a
> apply parallel worker. NULL if this process is a leader apply worker or a
> synchronization worker.
>
> IIUC, this text is just cut/paste from the monitoring.sgml. In a review comment
> below I suggest some changes to that text, so then this commit message
> should also change to be the same.
Changed.
> ~~
>
> 3.
>
> The new column can make it easier to distinguish leader apply worker and
> apply parallel worker which is also similar to the 'leader_pid' column in
> pg_stat_activity.
>
> SUGGESTION
> The new column makes it easier to distinguish parallel apply workers from
> other kinds of workers. It is implemented this way to be similar to the
> 'leader_pid' column in pg_stat_activity.
Changed.
> ======
>
> doc/src/sgml/logical-replication.sgml
>
> 4.
>
> + being synchronized. Moreover, if the streaming transaction is applied in
> + parallel, there will be additional workers.
>
> SUGGESTION
> there will be additional workers -> there may be additional parallel apply
> workers
Changed.
> ======
>
> doc/src/sgml/monitoring.sgml
>
> 5. pg_stat_subscription
>
> @@ -3198,11 +3198,22 @@ SELECT pid, wait_event_type, wait_event FROM
> pg_stat_activity WHERE wait_event i
>
> <row>
> <entry role="catalog_table_entry"><para role="column_definition">
> + <structfield>apply_leader_pid</structfield> <type>integer</type>
> + </para>
> + <para>
> + Process ID of the leader apply worker, if this process is a apply
> + parallel worker. NULL if this process is a leader apply worker or a
> + synchronization worker.
> + </para></entry>
> + </row>
> +
> + <row>
> + <entry role="catalog_table_entry"><para role="column_definition">
> <structfield>relid</structfield> <type>oid</type>
> </para>
> <para>
> OID of the relation that the worker is synchronizing; null for the
> - main apply worker
> + main apply worker and the parallel apply worker
> </para></entry>
> </row>
>
> 5a.
>
> (Same as general comment #1 about terminology)
>
> "apply_leader_pid" --> "leader_apply_pid"
I changed this and all related stuff to "leader_pid" as I agree with Amit that
this might be useful for future features and is more consistent with the
leader_pid in pg_stat_activity.
>
> ~~
>
> 5b.
>
> The current text feels awkward. I see it was copied from the similar text of
> 'pg_stat_activity' but perhaps it can be simplified a bit.
>
> SUGGESTION
> Process ID of the leader apply worker if this process is a parallel apply worker;
> otherwise NULL.
I slightly adjusted this according Amit's suggestion which I think would provide
more information.
"Process ID of the leader apply worker, if this process is a parallel apply worker.
NULL if this process is a leader apply worker or does not participate in parallel apply, or a synchronization worker."
"
> ~~
>
> 5c.
> BEFORE
> null for the main apply worker and the parallel apply worker
>
> AFTER
> null for the leader apply worker and parallel apply workers
Changed.
> ~~
>
> 5c.
>
> <structfield>relid</structfield> <type>oid</type>
> </para>
> <para>
> OID of the relation that the worker is synchronizing; null for the
> - main apply worker
> + main apply worker and the parallel apply worker
> </para></entry>
>
>
> main apply worker -> leader apply worker
>
Changed.
> ~~~
>
> 6.
>
> @@ -3212,7 +3223,7 @@ SELECT pid, wait_event_type, wait_event FROM
> pg_stat_activity WHERE wait_event i
> </para>
> <para>
> Last write-ahead log location received, the initial value of
> - this field being 0
> + this field being 0; null for the parallel apply worker
> </para></entry>
> </row>
>
> BEFORE
> null for the parallel apply worker
>
> AFTER
> null for parallel apply workers
>
Changed.
> ~~~
>
> 7.
>
> @@ -3221,7 +3232,8 @@ SELECT pid, wait_event_type, wait_event FROM
> pg_stat_activity WHERE wait_event i
> <structfield>last_msg_send_time</structfield> <type>timestamp
> with time zone</type>
> </para>
> <para>
> - Send time of last message received from origin WAL sender
> + Send time of last message received from origin WAL sender; null for
> the
> + parallel apply worker
> </para></entry>
> </row>
>
> (same as #6)
>
> BEFORE
> null for the parallel apply worker
>
> AFTER
> null for parallel apply workers
>
Changed.
> ~~~
>
> 8.
>
> @@ -3230,7 +3242,8 @@ SELECT pid, wait_event_type, wait_event FROM
> pg_stat_activity WHERE wait_event i
> <structfield>last_msg_receipt_time</structfield>
> <type>timestamp with time zone</type>
> </para>
> <para>
> - Receipt time of last message received from origin WAL sender
> + Receipt time of last message received from origin WAL sender; null for
> + the parallel apply worker
> </para></entry>
> </row>
>
> (same as #6)
>
> BEFORE
> null for the parallel apply worker
>
> AFTER
> null for parallel apply workers
>
Changed.
> ~~~
>
> 9.
>
> @@ -3239,7 +3252,8 @@ SELECT pid, wait_event_type, wait_event FROM
> pg_stat_activity WHERE wait_event i
> <structfield>latest_end_lsn</structfield> <type>pg_lsn</type>
> </para>
> <para>
> - Last write-ahead log location reported to origin WAL sender
> + Last write-ahead log location reported to origin WAL sender; null for
> + the parallel apply worker
> </para></entry>
> </row>
>
> (same as #6)
>
> BEFORE
> null for the parallel apply worker
>
> AFTER
> null for parallel apply workers
>
Changed.
> ~~~
>
> 10.
>
> @@ -3249,7 +3263,7 @@ SELECT pid, wait_event_type, wait_event FROM
> pg_stat_activity WHERE wait_event i
> </para>
> <para>
> Time of last write-ahead log location reported to origin WAL
> - sender
> + sender; null for the parallel apply worker
> </para></entry>
> </row>
> </tbody>
>
> (same as #6)
>
> BEFORE
> null for the parallel apply worker
>
> AFTER
> null for parallel apply workers
>
Changed.
> 12b.
>
> I wondered if here the code should be using the
> isParallelApplyWorker(worker) macro here for readability.
>
> e.g.
>
> if (isParallelApplyWorker(worker))
> values[3] = Int32GetDatum(worker.apply_leader_pid);
> else
> nulls[3] = true;
Changed.
Best Regards,
Hou Zhijie
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-10 05:46 ` Kyotaro Horiguchi <[email protected]>
2023-01-10 06:31 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
4 siblings, 1 reply; 105+ messages in thread
From: Kyotaro Horiguchi @ 2023-01-10 05:46 UTC (permalink / raw)
To: [email protected]; +Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
Hello.
At Mon, 9 Jan 2023 14:21:03 +0530, Amit Kapila <[email protected]> wrote in
> Pushed the first (0001) patch.
It added the following error message.
+ seg = dsm_attach(handle);
+ if (!seg)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("unable to map dynamic shared memory segment")));
On the other hand we already have the following one in parallel.c
(another in pg_prewarm)
seg = dsm_attach(DatumGetUInt32(main_arg));
if (seg == NULL)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("could not map dynamic shared memory segment")));
Although I don't see a technical difference between the two, all the
other occurances including the just above (except test_shm_mq) use
"could not". A faint memory in my non-durable memory tells me that we
have a policy that we use "can/could not" than "unable".
(Mmm. I find ones in StartBackgroundWorker and sepgsql_client_auth.)
Shouldn't we use the latter than the former? If that's true, it seems
to me that test_shm_mq also needs the same amendment to avoid the same
mistake in future.
=====
index 2e5914d5d9..a2d7474ed4 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -891,7 +891,7 @@ ParallelApplyWorkerMain(Datum main_arg)
if (!seg)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("unable to map dynamic shared memory segment")));
+ errmsg("could not map dynamic shared memory segment")));
toc = shm_toc_attach(PG_LOGICAL_APPLY_SHM_MAGIC, dsm_segment_address(seg));
if (!toc)
diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c
index 8807727337..005b56023b 100644
--- a/src/test/modules/test_shm_mq/worker.c
+++ b/src/test/modules/test_shm_mq/worker.c
@@ -81,7 +81,7 @@ test_shm_mq_main(Datum main_arg)
if (seg == NULL)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("unable to map dynamic shared memory segment")));
+ errmsg("could not map dynamic shared memory segment")));
toc = shm_toc_attach(PG_TEST_SHM_MQ_MAGIC, dsm_segment_address(seg));
if (toc == NULL)
ereport(ERROR,
=====
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-10 05:46 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
@ 2023-01-10 06:31 ` Amit Kapila <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: Amit Kapila @ 2023-01-10 06:31 UTC (permalink / raw)
To: Kyotaro Horiguchi <[email protected]>; +Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
On Tue, Jan 10, 2023 at 11:16 AM Kyotaro Horiguchi
<[email protected]> wrote:
>
> At Mon, 9 Jan 2023 14:21:03 +0530, Amit Kapila <[email protected]> wrote in
> > Pushed the first (0001) patch.
>
> It added the following error message.
>
> + seg = dsm_attach(handle);
> + if (!seg)
> + ereport(ERROR,
> + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("unable to map dynamic shared memory segment")));
>
> On the other hand we already have the following one in parallel.c
> (another in pg_prewarm)
>
> seg = dsm_attach(DatumGetUInt32(main_arg));
> if (seg == NULL)
> ereport(ERROR,
> (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> errmsg("could not map dynamic shared memory segment")));
>
> Although I don't see a technical difference between the two, all the
> other occurances including the just above (except test_shm_mq) use
> "could not". A faint memory in my non-durable memory tells me that we
> have a policy that we use "can/could not" than "unable".
>
Right, it is mentioned in docs [1] (see section "Tricky Words to Avoid").
> (Mmm. I find ones in StartBackgroundWorker and sepgsql_client_auth.)
>
> Shouldn't we use the latter than the former? If that's true, it seems
> to me that test_shm_mq also needs the same amendment to avoid the same
> mistake in future.
>
> =====
> index 2e5914d5d9..a2d7474ed4 100644
> --- a/src/backend/replication/logical/applyparallelworker.c
> +++ b/src/backend/replication/logical/applyparallelworker.c
> @@ -891,7 +891,7 @@ ParallelApplyWorkerMain(Datum main_arg)
> if (!seg)
> ereport(ERROR,
> (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> - errmsg("unable to map dynamic shared memory segment")));
> + errmsg("could not map dynamic shared memory segment")));
>
> toc = shm_toc_attach(PG_LOGICAL_APPLY_SHM_MAGIC, dsm_segment_address(seg));
> if (!toc)
> diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c
> index 8807727337..005b56023b 100644
> --- a/src/test/modules/test_shm_mq/worker.c
> +++ b/src/test/modules/test_shm_mq/worker.c
> @@ -81,7 +81,7 @@ test_shm_mq_main(Datum main_arg)
> if (seg == NULL)
> ereport(ERROR,
> (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> - errmsg("unable to map dynamic shared memory segment")));
> + errmsg("could not map dynamic shared memory segment")));
> toc = shm_toc_attach(PG_TEST_SHM_MQ_MAGIC, dsm_segment_address(seg));
> if (toc == NULL)
> ereport(ERROR,
> =====
>
Can you please start a new thread and post these changes as we are
proposing to change existing message as well?
[1] - https://www.postgresql.org/docs/devel/error-style-guide.html
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-15 17:09 ` Tomas Vondra <[email protected]>
2023-01-16 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
4 siblings, 1 reply; 105+ messages in thread
From: Tomas Vondra @ 2023-01-15 17:09 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; [email protected] <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
Hi,
I think there's a bug in how get_transaction_apply_action() interacts
with handle_streamed_transaction() to decide whether the transaction is
streamed or not. Originally, the code was simply:
/* not in streaming mode */
if (!in_streamed_transaction)
return false;
But now this decision was moved to get_transaction_apply_action(), which
does this:
if (am_parallel_apply_worker())
{
return TRANS_PARALLEL_APPLY;
}
else if (in_remote_transaction)
{
return TRANS_LEADER_APPLY;
}
and handle_streamed_transaction() then uses the result like this:
/* not in streaming mode */
if (apply_action == TRANS_LEADER_APPLY)
return false;
Notice this is not equal to the original behavior, because the two flags
(in_remote_transaction and in_streamed_transaction) are not inverse.
That is,
in_remote_transaction=false
does not imply we're processing streamed transaction. It's allowed both
flags are false, i.e. a change may be "non-transactional" and not
streamed, though the only example of such thing in the protocol are
logical messages. Which are however ignored in the apply worker, so I'm
not surprised no existing test failed on this.
So I think get_transaction_apply_action() should do this:
if (am_parallel_apply_worker())
{
return TRANS_PARALLEL_APPLY;
}
else if (!in_streamed_transaction)
{
return TRANS_LEADER_APPLY;
}
FWIW I've noticed this after rebasing the sequence decoding patch, which
adds another type of protocol message with the transactional vs.
non-transactional behavior, similar to "logical messages" except that in
this case the worker does not ignore that.
Also, I think get_transaction_apply_action() would deserve better
comments explaining how/why it makes the decisions.
regards
--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-15 17:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
@ 2023-01-16 06:19 ` Amit Kapila <[email protected]>
2023-01-16 16:33 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
2023-01-17 03:05 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 2 replies; 105+ messages in thread
From: Amit Kapila @ 2023-01-16 06:19 UTC (permalink / raw)
To: Tomas Vondra <[email protected]>; +Cc: [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Sun, Jan 15, 2023 at 10:39 PM Tomas Vondra
<[email protected]> wrote:
>
> I think there's a bug in how get_transaction_apply_action() interacts
> with handle_streamed_transaction() to decide whether the transaction is
> streamed or not. Originally, the code was simply:
>
> /* not in streaming mode */
> if (!in_streamed_transaction)
> return false;
>
> But now this decision was moved to get_transaction_apply_action(), which
> does this:
>
> if (am_parallel_apply_worker())
> {
> return TRANS_PARALLEL_APPLY;
> }
> else if (in_remote_transaction)
> {
> return TRANS_LEADER_APPLY;
> }
>
> and handle_streamed_transaction() then uses the result like this:
>
> /* not in streaming mode */
> if (apply_action == TRANS_LEADER_APPLY)
> return false;
>
> Notice this is not equal to the original behavior, because the two flags
> (in_remote_transaction and in_streamed_transaction) are not inverse.
> That is,
>
> in_remote_transaction=false
>
> does not imply we're processing streamed transaction. It's allowed both
> flags are false, i.e. a change may be "non-transactional" and not
> streamed, though the only example of such thing in the protocol are
> logical messages. Which are however ignored in the apply worker, so I'm
> not surprised no existing test failed on this.
>
Right, this is the reason we didn't catch it in our testing.
> So I think get_transaction_apply_action() should do this:
>
> if (am_parallel_apply_worker())
> {
> return TRANS_PARALLEL_APPLY;
> }
> else if (!in_streamed_transaction)
> {
> return TRANS_LEADER_APPLY;
> }
>
Yeah, something like this would work but some of the callers other
than handle_streamed_transaction() also need to be changed. See
attached.
> FWIW I've noticed this after rebasing the sequence decoding patch, which
> adds another type of protocol message with the transactional vs.
> non-transactional behavior, similar to "logical messages" except that in
> this case the worker does not ignore that.
>
> Also, I think get_transaction_apply_action() would deserve better
> comments explaining how/why it makes the decisions.
>
Okay, I have added the comments in get_transaction_apply_action() and
updated the comments to refer to the enum TransApplyAction where all
the actions are explained.
--
With Regards,
Amit Kapila.
Attachments:
[application/octet-stream] v1-0001-Fix-the-code-to-decide-the-apply-action.patch (4.6K, ../../CAA4eK1K9+pchebQ47zstp-cmK0epML=UbWvs=enECHDB2vDPvQ@mail.gmail.com/2-v1-0001-Fix-the-code-to-decide-the-apply-action.patch)
download | inline diff:
From 18491666729f9028cdaba611bd90874f75c2e132 Mon Sep 17 00:00:00 2001
From: Amit Kapila <[email protected]>
Date: Mon, 16 Jan 2023 10:49:38 +0530
Subject: [PATCH v1] Fix the code to decide the apply action.
The code missed to handle non-transactional messages and we didn't catch
it in our testing as currently such messages are simply ignored by the
apply worker. This was introduced by changes in commit 216a784829.
While testing this, I noticed that we forgot to reset stream_xid after
processing stream stop message which could also result in the wrong apply
action after the fix for non-transactional messages.
Reported-by: Tomas Vondra
Discussion: https://postgr.es/m/[email protected]
---
src/backend/replication/logical/worker.c | 53 ++++++++++++++++++++------------
1 file changed, 33 insertions(+), 20 deletions(-)
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 79cda39..7d1b1a8 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -247,8 +247,10 @@ typedef struct ApplyErrorCallbackArg
* The action to be taken for the changes in the transaction.
*
* TRANS_LEADER_APPLY:
- * This action means that we are in the leader apply worker and changes of the
- * transaction are applied directly by the worker.
+ * This action means that we are in the leader apply worker or table sync
+ * worker. The changes of the transaction are either directly applied or
+ * are read from temporary files (for streaming transactions) and then
+ * applied by the worker.
*
* TRANS_LEADER_SERIALIZE:
* This action means that we are in the leader apply worker or table sync
@@ -1301,7 +1303,7 @@ apply_handle_stream_prepare(StringInfo s)
switch (apply_action)
{
- case TRANS_LEADER_SERIALIZE:
+ case TRANS_LEADER_APPLY:
/*
* The transaction has been serialized to file, so replay all the
@@ -1710,6 +1712,7 @@ apply_handle_stream_stop(StringInfo s)
}
in_streamed_transaction = false;
+ stream_xid = InvalidTransactionId;
/*
* The parallel apply worker could be in a transaction in which case we
@@ -1842,7 +1845,7 @@ apply_handle_stream_abort(StringInfo s)
switch (apply_action)
{
- case TRANS_LEADER_SERIALIZE:
+ case TRANS_LEADER_APPLY:
/*
* We are in the leader apply worker and the transaction has been
@@ -2164,7 +2167,7 @@ apply_handle_stream_commit(StringInfo s)
switch (apply_action)
{
- case TRANS_LEADER_SERIALIZE:
+ case TRANS_LEADER_APPLY:
/*
* The transaction has been serialized to file, so replay all the
@@ -4996,10 +4999,12 @@ set_apply_error_context_origin(char *originname)
}
/*
- * Return the action to be taken for the given transaction. *winfo is
- * assigned to the destination parallel worker info when the leader apply
- * worker has to pass all the transaction's changes to the parallel apply
- * worker.
+ * Return the action to be taken for the given transaction. See
+ * TransApplyAction for information on each of the actions.
+ *
+ * *winfo is assigned to the destination parallel worker info when the leader
+ * apply worker has to pass all the transaction's changes to the parallel
+ * apply worker.
*/
static TransApplyAction
get_transaction_apply_action(TransactionId xid, ParallelApplyWorkerInfo **winfo)
@@ -5010,27 +5015,35 @@ get_transaction_apply_action(TransactionId xid, ParallelApplyWorkerInfo **winfo)
{
return TRANS_PARALLEL_APPLY;
}
- else if (in_remote_transaction)
- {
- return TRANS_LEADER_APPLY;
- }
/*
- * Check if we are processing this transaction using a parallel apply
- * worker.
+ * If we are processing this transaction using a parallel apply worker then
+ * either we send the changes to the parallel worker or if the worker is busy
+ * then serialize the changes to the file which will later be processed by
+ * the parallel worker.
*/
*winfo = pa_find_worker(xid);
- if (!*winfo)
+ if (*winfo && (*winfo)->serialize_changes)
{
- return TRANS_LEADER_SERIALIZE;
+ return TRANS_LEADER_PARTIAL_SERIALIZE;
}
- else if ((*winfo)->serialize_changes)
+ else if (*winfo)
{
- return TRANS_LEADER_PARTIAL_SERIALIZE;
+ return TRANS_LEADER_SEND_TO_PARALLEL;
+ }
+
+ /*
+ * If there is no parallel worker involved to process this transaction then
+ * we either directly apply the change or serialize it to a file which will
+ * later be applied when the transaction finish message is processed.
+ */
+ else if (in_streamed_transaction)
+ {
+ return TRANS_LEADER_SERIALIZE;
}
else
{
- return TRANS_LEADER_SEND_TO_PARALLEL;
+ return TRANS_LEADER_APPLY;
}
}
--
1.8.3.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-15 17:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
2023-01-16 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-16 16:33 ` Tomas Vondra <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: Tomas Vondra @ 2023-01-16 16:33 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: [email protected] <[email protected]>; Masahiko Sawada <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
Hi Amit,
Thanks for the patch, the changes seem reasonable to me and it does fix
the issue in the sequence decoding patch.
regards
--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-15 17:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
2023-01-16 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-17 03:05 ` Masahiko Sawada <[email protected]>
2023-01-17 03:29 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
1 sibling, 1 reply; 105+ messages in thread
From: Masahiko Sawada @ 2023-01-17 03:05 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Tomas Vondra <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Mon, Jan 16, 2023 at 3:19 PM Amit Kapila <[email protected]> wrote:
>
> On Sun, Jan 15, 2023 at 10:39 PM Tomas Vondra
> <[email protected]> wrote:
> >
> > I think there's a bug in how get_transaction_apply_action() interacts
> > with handle_streamed_transaction() to decide whether the transaction is
> > streamed or not. Originally, the code was simply:
> >
> > /* not in streaming mode */
> > if (!in_streamed_transaction)
> > return false;
> >
> > But now this decision was moved to get_transaction_apply_action(), which
> > does this:
> >
> > if (am_parallel_apply_worker())
> > {
> > return TRANS_PARALLEL_APPLY;
> > }
> > else if (in_remote_transaction)
> > {
> > return TRANS_LEADER_APPLY;
> > }
> >
> > and handle_streamed_transaction() then uses the result like this:
> >
> > /* not in streaming mode */
> > if (apply_action == TRANS_LEADER_APPLY)
> > return false;
> >
> > Notice this is not equal to the original behavior, because the two flags
> > (in_remote_transaction and in_streamed_transaction) are not inverse.
> > That is,
> >
> > in_remote_transaction=false
> >
> > does not imply we're processing streamed transaction. It's allowed both
> > flags are false, i.e. a change may be "non-transactional" and not
> > streamed, though the only example of such thing in the protocol are
> > logical messages. Which are however ignored in the apply worker, so I'm
> > not surprised no existing test failed on this.
> >
>
> Right, this is the reason we didn't catch it in our testing.
>
> > So I think get_transaction_apply_action() should do this:
> >
> > if (am_parallel_apply_worker())
> > {
> > return TRANS_PARALLEL_APPLY;
> > }
> > else if (!in_streamed_transaction)
> > {
> > return TRANS_LEADER_APPLY;
> > }
> >
>
> Yeah, something like this would work but some of the callers other
> than handle_streamed_transaction() also need to be changed. See
> attached.
>
> > FWIW I've noticed this after rebasing the sequence decoding patch, which
> > adds another type of protocol message with the transactional vs.
> > non-transactional behavior, similar to "logical messages" except that in
> > this case the worker does not ignore that.
> >
> > Also, I think get_transaction_apply_action() would deserve better
> > comments explaining how/why it makes the decisions.
> >
>
> Okay, I have added the comments in get_transaction_apply_action() and
> updated the comments to refer to the enum TransApplyAction where all
> the actions are explained.
Thank you for the patch.
@@ -1710,6 +1712,7 @@ apply_handle_stream_stop(StringInfo s)
}
in_streamed_transaction = false;
+ stream_xid = InvalidTransactionId;
We reset stream_xid also in stream_close_file() but probably it's no
longer necessary?
How about adding an assertion in apply_handle_stream_start() to make
sure the stream_xid is invalid?
---
It's not related to this issue but I realized that if the action
returned by get_transaction_apply_action() is not handled in the
switch statement, we do only Assert(false). Is it better to raise an
error like "unexpected apply action %d" just in case in order to
detect failure cases also in the production environment?
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-15 17:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
2023-01-16 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-17 03:05 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-01-17 03:29 ` Amit Kapila <[email protected]>
2023-01-17 04:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-01-17 03:29 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: Tomas Vondra <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Tue, Jan 17, 2023 at 8:35 AM Masahiko Sawada <[email protected]> wrote:
>
> On Mon, Jan 16, 2023 at 3:19 PM Amit Kapila <[email protected]> wrote:
> >
> > Okay, I have added the comments in get_transaction_apply_action() and
> > updated the comments to refer to the enum TransApplyAction where all
> > the actions are explained.
>
> Thank you for the patch.
>
> @@ -1710,6 +1712,7 @@ apply_handle_stream_stop(StringInfo s)
> }
>
> in_streamed_transaction = false;
> + stream_xid = InvalidTransactionId;
>
> We reset stream_xid also in stream_close_file() but probably it's no
> longer necessary?
>
I think so.
> How about adding an assertion in apply_handle_stream_start() to make
> sure the stream_xid is invalid?
>
I think it would be better to add such an assert in
apply_handle_begin/apply_handle_begin_prepare because there won't be a
problem if we start_stream message even when stream_xid is valid.
However, maybe it is better to add in all three functions
(apply_handle_begin/apply_handle_begin_prepare/apply_handle_stream_start).
What do you think?
> ---
> It's not related to this issue but I realized that if the action
> returned by get_transaction_apply_action() is not handled in the
> switch statement, we do only Assert(false). Is it better to raise an
> error like "unexpected apply action %d" just in case in order to
> detect failure cases also in the production environment?
>
Yeah, that may be better. Shall we do that as part of this patch only
or as a separate patch?
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-15 17:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
2023-01-16 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-17 03:05 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-17 03:29 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-17 04:55 ` Amit Kapila <[email protected]>
2023-01-17 05:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-17 06:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
0 siblings, 2 replies; 105+ messages in thread
From: Amit Kapila @ 2023-01-17 04:55 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: Tomas Vondra <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Tue, Jan 17, 2023 at 8:59 AM Amit Kapila <[email protected]> wrote:
>
> On Tue, Jan 17, 2023 at 8:35 AM Masahiko Sawada <[email protected]> wrote:
> >
> > On Mon, Jan 16, 2023 at 3:19 PM Amit Kapila <[email protected]> wrote:
> > >
> > > Okay, I have added the comments in get_transaction_apply_action() and
> > > updated the comments to refer to the enum TransApplyAction where all
> > > the actions are explained.
> >
> > Thank you for the patch.
> >
> > @@ -1710,6 +1712,7 @@ apply_handle_stream_stop(StringInfo s)
> > }
> >
> > in_streamed_transaction = false;
> > + stream_xid = InvalidTransactionId;
> >
> > We reset stream_xid also in stream_close_file() but probably it's no
> > longer necessary?
> >
>
> I think so.
>
> > How about adding an assertion in apply_handle_stream_start() to make
> > sure the stream_xid is invalid?
> >
>
> I think it would be better to add such an assert in
> apply_handle_begin/apply_handle_begin_prepare because there won't be a
> problem if we start_stream message even when stream_xid is valid.
> However, maybe it is better to add in all three functions
> (apply_handle_begin/apply_handle_begin_prepare/apply_handle_stream_start).
> What do you think?
>
> > ---
> > It's not related to this issue but I realized that if the action
> > returned by get_transaction_apply_action() is not handled in the
> > switch statement, we do only Assert(false). Is it better to raise an
> > error like "unexpected apply action %d" just in case in order to
> > detect failure cases also in the production environment?
> >
>
> Yeah, that may be better. Shall we do that as part of this patch only
> or as a separate patch?
>
Please find attached the updated patches to address the above
comments. I think we can combine and commit them as one patch as both
are related.
--
With Regards,
Amit Kapila.
Attachments:
[application/octet-stream] v2-0001-Improve-the-code-to-decide-the-apply-action.patch (5.9K, ../../CAA4eK1LqrJAKPjYuuhURokKk2edSU5WV8svzD3rpxa6mqy_eWA@mail.gmail.com/2-v2-0001-Improve-the-code-to-decide-the-apply-action.patch)
download | inline diff:
From e05b4966f4bbf05e086274ae19d3fcc65e469064 Mon Sep 17 00:00:00 2001
From: Amit Kapila <[email protected]>
Date: Tue, 17 Jan 2023 09:18:14 +0530
Subject: [PATCH v2 1/2] Improve the code to decide the apply action.
The code missed to handle non-transactional messages and we didn't catch
it in our testing as currently such messages are simply ignored by the
apply worker. This was introduced by changes in commit 216a784829.
While testing this, I noticed that we forgot to reset stream_xid after
processing the stream stop message which could also result in the wrong
apply action after the fix for non-transactional messages.
Reported-by: Tomas Vondra
Author: Amit Kapila
Reviewed-by: Tomas Vondra, Sawada Masahiko
Discussion: https://postgr.es/m/[email protected]
---
src/backend/replication/logical/worker.c | 63 ++++++++++++++++--------
1 file changed, 42 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index d8b8a374c6..ce14b7a685 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -247,8 +247,10 @@ typedef struct ApplyErrorCallbackArg
* The action to be taken for the changes in the transaction.
*
* TRANS_LEADER_APPLY:
- * This action means that we are in the leader apply worker and changes of the
- * transaction are applied directly by the worker.
+ * This action means that we are in the leader apply worker or table sync
+ * worker. The changes of the transaction are either directly applied or
+ * are read from temporary files (for streaming transactions) and then
+ * applied by the worker.
*
* TRANS_LEADER_SERIALIZE:
* This action means that we are in the leader apply worker or table sync
@@ -1004,6 +1006,9 @@ apply_handle_begin(StringInfo s)
{
LogicalRepBeginData begin_data;
+ /* There must not be an active streaming transaction. */
+ Assert(!TransactionIdIsValid(stream_xid));
+
logicalrep_read_begin(s, &begin_data);
set_apply_error_context_xact(begin_data.xid, begin_data.final_lsn);
@@ -1058,6 +1063,9 @@ apply_handle_begin_prepare(StringInfo s)
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg_internal("tablesync worker received a BEGIN PREPARE message")));
+ /* There must not be an active streaming transaction. */
+ Assert(!TransactionIdIsValid(stream_xid));
+
logicalrep_read_begin_prepare(s, &begin_data);
set_apply_error_context_xact(begin_data.xid, begin_data.prepare_lsn);
@@ -1301,7 +1309,7 @@ apply_handle_stream_prepare(StringInfo s)
switch (apply_action)
{
- case TRANS_LEADER_SERIALIZE:
+ case TRANS_LEADER_APPLY:
/*
* The transaction has been serialized to file, so replay all the
@@ -1484,6 +1492,9 @@ apply_handle_stream_start(StringInfo s)
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg_internal("duplicate STREAM START message")));
+ /* There must not be an active streaming transaction. */
+ Assert(!TransactionIdIsValid(stream_xid));
+
/* notify handle methods we're processing a remote transaction */
in_streamed_transaction = true;
@@ -1710,6 +1721,7 @@ apply_handle_stream_stop(StringInfo s)
}
in_streamed_transaction = false;
+ stream_xid = InvalidTransactionId;
/*
* The parallel apply worker could be in a transaction in which case we
@@ -1842,7 +1854,7 @@ apply_handle_stream_abort(StringInfo s)
switch (apply_action)
{
- case TRANS_LEADER_SERIALIZE:
+ case TRANS_LEADER_APPLY:
/*
* We are in the leader apply worker and the transaction has been
@@ -2154,7 +2166,7 @@ apply_handle_stream_commit(StringInfo s)
switch (apply_action)
{
- case TRANS_LEADER_SERIALIZE:
+ case TRANS_LEADER_APPLY:
/*
* The transaction has been serialized to file, so replay all the
@@ -4204,7 +4216,6 @@ stream_close_file(void)
BufFileClose(stream_fd);
- stream_xid = InvalidTransactionId;
stream_fd = NULL;
}
@@ -4977,10 +4988,12 @@ set_apply_error_context_origin(char *originname)
}
/*
- * Return the action to be taken for the given transaction. *winfo is
- * assigned to the destination parallel worker info when the leader apply
- * worker has to pass all the transaction's changes to the parallel apply
- * worker.
+ * Return the action to be taken for the given transaction. See
+ * TransApplyAction for information on each of the actions.
+ *
+ * *winfo is assigned to the destination parallel worker info when the leader
+ * apply worker has to pass all the transaction's changes to the parallel
+ * apply worker.
*/
static TransApplyAction
get_transaction_apply_action(TransactionId xid, ParallelApplyWorkerInfo **winfo)
@@ -4991,27 +5004,35 @@ get_transaction_apply_action(TransactionId xid, ParallelApplyWorkerInfo **winfo)
{
return TRANS_PARALLEL_APPLY;
}
- else if (in_remote_transaction)
- {
- return TRANS_LEADER_APPLY;
- }
/*
- * Check if we are processing this transaction using a parallel apply
- * worker.
+ * If we are processing this transaction using a parallel apply worker then
+ * either we send the changes to the parallel worker or if the worker is busy
+ * then serialize the changes to the file which will later be processed by
+ * the parallel worker.
*/
*winfo = pa_find_worker(xid);
- if (!*winfo)
+ if (*winfo && (*winfo)->serialize_changes)
{
- return TRANS_LEADER_SERIALIZE;
+ return TRANS_LEADER_PARTIAL_SERIALIZE;
}
- else if ((*winfo)->serialize_changes)
+ else if (*winfo)
{
- return TRANS_LEADER_PARTIAL_SERIALIZE;
+ return TRANS_LEADER_SEND_TO_PARALLEL;
+ }
+
+ /*
+ * If there is no parallel worker involved to process this transaction then
+ * we either directly apply the change or serialize it to a file which will
+ * later be applied when the transaction finish message is processed.
+ */
+ else if (in_streamed_transaction)
+ {
+ return TRANS_LEADER_SERIALIZE;
}
else
{
- return TRANS_LEADER_SEND_TO_PARALLEL;
+ return TRANS_LEADER_APPLY;
}
}
--
2.28.0.windows.1
[application/octet-stream] v2-0002-Change-assert-to-elog-for-unexpected-apply-action.patch (1.5K, ../../CAA4eK1LqrJAKPjYuuhURokKk2edSU5WV8svzD3rpxa6mqy_eWA@mail.gmail.com/3-v2-0002-Change-assert-to-elog-for-unexpected-apply-action.patch)
download | inline diff:
From 5ae0b61ec14c6bc32f077f8c557f89f3c06bdeb2 Mon Sep 17 00:00:00 2001
From: Amit Kapila <[email protected]>
Date: Tue, 17 Jan 2023 09:45:35 +0530
Subject: [PATCH v2 2/2] Change assert to elog for unexpected apply action.
---
src/backend/replication/logical/worker.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index ce14b7a685..a0084c7ef6 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -1392,7 +1392,7 @@ apply_handle_stream_prepare(StringInfo s)
break;
default:
- Assert(false);
+ elog(ERROR, "unexpected apply action: %d", (int) apply_action);
break;
}
@@ -1600,7 +1600,7 @@ apply_handle_stream_start(StringInfo s)
break;
default:
- Assert(false);
+ elog(ERROR, "unexpected apply action: %d", (int) apply_action);
break;
}
@@ -1716,7 +1716,7 @@ apply_handle_stream_stop(StringInfo s)
break;
default:
- Assert(false);
+ elog(ERROR, "unexpected apply action: %d", (int) apply_action);
break;
}
@@ -1969,7 +1969,7 @@ apply_handle_stream_abort(StringInfo s)
break;
default:
- Assert(false);
+ elog(ERROR, "unexpected apply action: %d", (int) apply_action);
break;
}
@@ -2238,7 +2238,7 @@ apply_handle_stream_commit(StringInfo s)
break;
default:
- Assert(false);
+ elog(ERROR, "unexpected apply action: %d", (int) apply_action);
break;
}
--
2.28.0.windows.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-15 17:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
2023-01-16 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-17 03:05 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-17 03:29 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-17 04:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-17 05:07 ` Masahiko Sawada <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: Masahiko Sawada @ 2023-01-17 05:07 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Tomas Vondra <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Tue, Jan 17, 2023 at 1:55 PM Amit Kapila <[email protected]> wrote:
>
> On Tue, Jan 17, 2023 at 8:59 AM Amit Kapila <[email protected]> wrote:
> >
> > On Tue, Jan 17, 2023 at 8:35 AM Masahiko Sawada <[email protected]> wrote:
> > >
> > > On Mon, Jan 16, 2023 at 3:19 PM Amit Kapila <[email protected]> wrote:
> > > >
> > > > Okay, I have added the comments in get_transaction_apply_action() and
> > > > updated the comments to refer to the enum TransApplyAction where all
> > > > the actions are explained.
> > >
> > > Thank you for the patch.
> > >
> > > @@ -1710,6 +1712,7 @@ apply_handle_stream_stop(StringInfo s)
> > > }
> > >
> > > in_streamed_transaction = false;
> > > + stream_xid = InvalidTransactionId;
> > >
> > > We reset stream_xid also in stream_close_file() but probably it's no
> > > longer necessary?
> > >
> >
> > I think so.
> >
> > > How about adding an assertion in apply_handle_stream_start() to make
> > > sure the stream_xid is invalid?
> > >
> >
> > I think it would be better to add such an assert in
> > apply_handle_begin/apply_handle_begin_prepare because there won't be a
> > problem if we start_stream message even when stream_xid is valid.
> > However, maybe it is better to add in all three functions
> > (apply_handle_begin/apply_handle_begin_prepare/apply_handle_stream_start).
> > What do you think?
> >
> > > ---
> > > It's not related to this issue but I realized that if the action
> > > returned by get_transaction_apply_action() is not handled in the
> > > switch statement, we do only Assert(false). Is it better to raise an
> > > error like "unexpected apply action %d" just in case in order to
> > > detect failure cases also in the production environment?
> > >
> >
> > Yeah, that may be better. Shall we do that as part of this patch only
> > or as a separate patch?
> >
>
> Please find attached the updated patches to address the above
> comments. I think we can combine and commit them as one patch as both
> are related.
Thank you for the patches! Looks good to me. And +1 to merge them.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-15 17:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
2023-01-16 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-17 03:05 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-17 03:29 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-17 04:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-01-17 06:05 ` [email protected] <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: [email protected] @ 2023-01-17 06:05 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Tomas Vondra <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>; Masahiko Sawada <[email protected]>
On Tuesday, January 17, 2023 12:55 PM Amit Kapila <[email protected]> wrote:
>
> On Tue, Jan 17, 2023 at 8:59 AM Amit Kapila <[email protected]> wrote:
> >
> > On Tue, Jan 17, 2023 at 8:35 AM Masahiko Sawada
> <[email protected]> wrote:
> > >
> > > On Mon, Jan 16, 2023 at 3:19 PM Amit Kapila <[email protected]>
> wrote:
> > > >
> > > > Okay, I have added the comments in get_transaction_apply_action()
> > > > and updated the comments to refer to the enum TransApplyAction
> > > > where all the actions are explained.
> > >
> > > Thank you for the patch.
> > >
> > > @@ -1710,6 +1712,7 @@ apply_handle_stream_stop(StringInfo s)
> > > }
> > >
> > > in_streamed_transaction = false;
> > > + stream_xid = InvalidTransactionId;
> > >
> > > We reset stream_xid also in stream_close_file() but probably it's no
> > > longer necessary?
> > >
> >
> > I think so.
> >
> > > How about adding an assertion in apply_handle_stream_start() to make
> > > sure the stream_xid is invalid?
> > >
> >
> > I think it would be better to add such an assert in
> > apply_handle_begin/apply_handle_begin_prepare because there won't be a
> > problem if we start_stream message even when stream_xid is valid.
> > However, maybe it is better to add in all three functions
> >
> (apply_handle_begin/apply_handle_begin_prepare/apply_handle_stream_star
> t).
> > What do you think?
> >
> > > ---
> > > It's not related to this issue but I realized that if the action
> > > returned by get_transaction_apply_action() is not handled in the
> > > switch statement, we do only Assert(false). Is it better to raise an
> > > error like "unexpected apply action %d" just in case in order to
> > > detect failure cases also in the production environment?
> > >
> >
> > Yeah, that may be better. Shall we do that as part of this patch only
> > or as a separate patch?
> >
>
> Please find attached the updated patches to address the above comments. I
> think we can combine and commit them as one patch as both are related.
Thanks for fixing these.
I have confirmed that all regression tests passed after applying the patches.
And the patches look good to me.
Best regards,
Hou zj
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-04-24 01:55 ` Masahiko Sawada <[email protected]>
2023-04-24 02:50 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
4 siblings, 2 replies; 105+ messages in thread
From: Masahiko Sawada @ 2023-04-24 01:55 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: [email protected] <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Mon, Jan 9, 2023 at 5:51 PM Amit Kapila <[email protected]> wrote:
>
> On Sun, Jan 8, 2023 at 11:32 AM [email protected]
> <[email protected]> wrote:
> >
> > On Sunday, January 8, 2023 11:59 AM [email protected] <[email protected]> wrote:
> > > Attach the updated patch set.
> >
> > Sorry, the commit message of 0001 was accidentally deleted, just attach
> > the same patch set again with commit message.
> >
>
> Pushed the first (0001) patch.
While looking at the worker.c, I realized that we have the following
code in handle_streamed_transaction():
default:
Assert(false);
return false; / silence compiler warning /
I think it's better to do elog(ERROR) instead of Assert() as it ends
up returning false in non-assertion builds, which might cause a
problem. And it's more consistent with other codes in worker.c. Please
find an attached patch.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
Attachments:
[application/octet-stream] 0001-Use-elog-to-report-unexpected-action-in-handle_strea.patch (956B, ../../CAD21AoDDbM8_HJt-nMCvcjTK8K9hPzXWqJj7pyaUvR4mm_NrSg@mail.gmail.com/2-0001-Use-elog-to-report-unexpected-action-in-handle_strea.patch)
download | inline diff:
From 7668789ee63bcb7155cfc92f813bab7d90cf8035 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <[email protected]>
Date: Mon, 24 Apr 2023 10:38:00 +0900
Subject: [PATCH] Use elog to report unexpected action in
handle_streamed_transaction().
An oversight in commit 216a784829c.
Author: Masahiko Sawada
Reviewed-by:
Discussion: https://postgr.es/m/
---
src/backend/replication/logical/worker.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 37bb884127..dbf88c9553 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -658,7 +658,7 @@ handle_streamed_transaction(LogicalRepMsgType action, StringInfo s)
return false;
default:
- Assert(false);
+ elog(ERROR, "unexpected apply action: %d", (int) apply_action);
return false; /* silence compiler warning */
}
}
--
2.31.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-04-24 02:50 ` Kyotaro Horiguchi <[email protected]>
2023-04-24 03:10 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
1 sibling, 1 reply; 105+ messages in thread
From: Kyotaro Horiguchi @ 2023-04-24 02:50 UTC (permalink / raw)
To: [email protected]; +Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
At Mon, 24 Apr 2023 10:55:44 +0900, Masahiko Sawada <[email protected]> wrote in
> While looking at the worker.c, I realized that we have the following
> code in handle_streamed_transaction():
>
> default:
> Assert(false);
> return false; / silence compiler warning /
>
> I think it's better to do elog(ERROR) instead of Assert() as it ends
> up returning false in non-assertion builds, which might cause a
> problem. And it's more consistent with other codes in worker.c. Please
> find an attached patch.
I concur that returning false is problematic.
For assertion builds, Assert typically provides more detailed
information than elog. However, in this case, it wouldn't matter much
since the worker would repeatedly restart even after a server-restart
for the same reason unless cosmic rays are involved. Moreover, the
situation doesn't justify server-restaring, as it would unnecessarily
involve other backends.
In my opinion, it is fine to replace the Assert with an ERROR.
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 02:50 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
@ 2023-04-24 03:10 ` Kyotaro Horiguchi <[email protected]>
2023-04-24 03:29 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Kyotaro Horiguchi @ 2023-04-24 03:10 UTC (permalink / raw)
To: [email protected]; +Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
At Mon, 24 Apr 2023 11:50:37 +0900 (JST), Kyotaro Horiguchi <[email protected]> wrote in
> In my opinion, it is fine to replace the Assert with an ERROR.
Sorry for posting multiple times in a row, but I'm a bit unceratin
whether we should use FATAL or ERROR for this situation. The stream is
not provided by user, and the session or process cannot continue.
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 02:50 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
2023-04-24 03:10 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
@ 2023-04-24 03:29 ` Amit Kapila <[email protected]>
2023-04-24 04:03 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-04-24 03:29 UTC (permalink / raw)
To: Kyotaro Horiguchi <[email protected]>; +Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
On Mon, Apr 24, 2023 at 8:40 AM Kyotaro Horiguchi
<[email protected]> wrote:
>
> At Mon, 24 Apr 2023 11:50:37 +0900 (JST), Kyotaro Horiguchi <[email protected]> wrote in
> > In my opinion, it is fine to replace the Assert with an ERROR.
>
> Sorry for posting multiple times in a row, but I'm a bit unceratin
> whether we should use FATAL or ERROR for this situation. The stream is
> not provided by user, and the session or process cannot continue.
>
I think ERROR should be fine here similar to other cases in worker.c.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 02:50 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
2023-04-24 03:10 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
2023-04-24 03:29 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-04-24 04:03 ` Kyotaro Horiguchi <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: Kyotaro Horiguchi @ 2023-04-24 04:03 UTC (permalink / raw)
To: [email protected]; +Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
At Mon, 24 Apr 2023 08:59:07 +0530, Amit Kapila <[email protected]> wrote in
> > Sorry for posting multiple times in a row, but I'm a bit unceratin
> > whether we should use FATAL or ERROR for this situation. The stream is
> > not provided by user, and the session or process cannot continue.
> >
>
> I think ERROR should be fine here similar to other cases in worker.c.
Sure, I don't have any issues with it.
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-04-24 05:24 ` Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
1 sibling, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-04-24 05:24 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: [email protected] <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Mon, Apr 24, 2023 at 7:26 AM Masahiko Sawada <[email protected]> wrote:
>
> While looking at the worker.c, I realized that we have the following
> code in handle_streamed_transaction():
>
> default:
> Assert(false);
> return false; / silence compiler warning /
>
> I think it's better to do elog(ERROR) instead of Assert() as it ends
> up returning false in non-assertion builds, which might cause a
> problem. And it's more consistent with other codes in worker.c. Please
> find an attached patch.
>
I haven't tested it but otherwise, the changes look good to me.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-04-24 06:42 ` Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Masahiko Sawada @ 2023-04-24 06:42 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: [email protected] <[email protected]>; [email protected] <[email protected]>; Peter Smith <[email protected]>; [email protected] <[email protected]>; PostgreSQL Hackers <[email protected]>; Dilip Kumar <[email protected]>
On Mon, Apr 24, 2023 at 2:24 PM Amit Kapila <[email protected]> wrote:
>
> On Mon, Apr 24, 2023 at 7:26 AM Masahiko Sawada <[email protected]> wrote:
> >
> > While looking at the worker.c, I realized that we have the following
> > code in handle_streamed_transaction():
> >
> > default:
> > Assert(false);
> > return false; / silence compiler warning /
> >
> > I think it's better to do elog(ERROR) instead of Assert() as it ends
> > up returning false in non-assertion builds, which might cause a
> > problem. And it's more consistent with other codes in worker.c. Please
> > find an attached patch.
> >
>
> I haven't tested it but otherwise, the changes look good to me.
Thanks for checking! Pushed.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-04-26 09:00 ` Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Alexander Lakhin @ 2023-04-26 09:00 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; Amit Kapila <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
Hello hackers,
Please look at a new anomaly that can be observed starting from 216a7848.
The following script:
echo "CREATE SUBSCRIPTION testsub CONNECTION 'dbname=nodb' PUBLICATION testpub WITH (connect = false);
ALTER SUBSCRIPTION testsub ENABLE;" | psql
sleep 1
rm $PGINST/lib/libpqwalreceiver.so
sleep 15
pg_ctl -D "$PGDB" stop -m immediate
grep 'TRAP:' server.log
Leads to multiple assertion failures:
CREATE SUBSCRIPTION
ALTER SUBSCRIPTION
waiting for server to shut down.... done
server stopped
TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c", Line: 4439, PID: 2899323
TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c", Line: 4439, PID: 2899416
TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c", Line: 4439, PID: 2899427
TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c", Line: 4439, PID: 2899439
TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c", Line: 4439, PID: 2899538
TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c", Line: 4439, PID: 2899547
server.log contains:
2023-04-26 11:00:58.797 MSK [2899300] LOG: database system is ready to accept connections
2023-04-26 11:00:58.821 MSK [2899416] ERROR: could not access file "libpqwalreceiver": No such file or directory
TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c", Line: 4439, PID: 2899416
postgres: logical replication apply worker for subscription 16385 (ExceptionalCondition+0x69)[0x558b2ac06d41]
postgres: logical replication apply worker for subscription 16385 (VirtualXactLockTableCleanup+0xa4)[0x558b2aa9fd74]
postgres: logical replication apply worker for subscription 16385 (LockReleaseAll+0xbb)[0x558b2aa9fe7d]
postgres: logical replication apply worker for subscription 16385 (+0x4588c6)[0x558b2aa2a8c6]
postgres: logical replication apply worker for subscription 16385 (shmem_exit+0x6c)[0x558b2aa87eb1]
postgres: logical replication apply worker for subscription 16385 (+0x4b5faa)[0x558b2aa87faa]
postgres: logical replication apply worker for subscription 16385 (proc_exit+0xc)[0x558b2aa88031]
postgres: logical replication apply worker for subscription 16385 (StartBackgroundWorker+0x147)[0x558b2aa0b4d9]
postgres: logical replication apply worker for subscription 16385 (+0x43fdc1)[0x558b2aa11dc1]
postgres: logical replication apply worker for subscription 16385 (+0x43ff3d)[0x558b2aa11f3d]
postgres: logical replication apply worker for subscription 16385 (+0x440866)[0x558b2aa12866]
postgres: logical replication apply worker for subscription 16385 (+0x440e12)[0x558b2aa12e12]
postgres: logical replication apply worker for subscription 16385 (BackgroundWorkerInitializeConnection+0x0)[0x558b2aa14396]
postgres: logical replication apply worker for subscription 16385 (main+0x21a)[0x558b2a932e21]
I understand, that removing libpqwalreceiver.so (or whole pginst/) is not
what happens in a production environment every day, but nonetheless it's a
new failure mode and it can produce many coredumps when testing.
IIUC, that assert will fail in case of any error raised between
ApplyWorkerMain()->logicalrep_worker_attach()->before_shmem_exit() and
ApplyWorkerMain()->InitializeApplyWorker()->BackgroundWorkerInitializeConnectionByOid()->InitPostgres().
Best regards,
Alexander
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
@ 2023-04-26 10:41 ` Zhijie Hou (Fujitsu) <[email protected]>
2023-04-26 11:21 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 2 replies; 105+ messages in thread
From: Zhijie Hou (Fujitsu) @ 2023-04-26 10:41 UTC (permalink / raw)
To: Alexander Lakhin <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Masahiko Sawada <[email protected]>; Amit Kapila <[email protected]>
On Wednesday, April 26, 2023 5:00 PM Alexander Lakhin <[email protected]> wrote:
> Please look at a new anomaly that can be observed starting from 216a7848.
>
> The following script:
> echo "CREATE SUBSCRIPTION testsub CONNECTION 'dbname=nodb'
> PUBLICATION testpub WITH (connect = false);
> ALTER SUBSCRIPTION testsub ENABLE;" | psql
>
> sleep 1
> rm $PGINST/lib/libpqwalreceiver.so
> sleep 15
> pg_ctl -D "$PGDB" stop -m immediate
> grep 'TRAP:' server.log
>
> Leads to multiple assertion failures:
> CREATE SUBSCRIPTION
> ALTER SUBSCRIPTION
> waiting for server to shut down.... done
> server stopped
> TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c",
> Line: 4439, PID: 2899323
> TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c",
> Line: 4439, PID: 2899416
> TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c",
> Line: 4439, PID: 2899427
> TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c",
> Line: 4439, PID: 2899439
> TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c",
> Line: 4439, PID: 2899538
> TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c",
> Line: 4439, PID: 2899547
>
> server.log contains:
> 2023-04-26 11:00:58.797 MSK [2899300] LOG: database system is ready to
> accept connections
> 2023-04-26 11:00:58.821 MSK [2899416] ERROR: could not access file
> "libpqwalreceiver": No such file or directory
> TRAP: failed Assert("MyProc->backendId != InvalidBackendId"), File: "lock.c",
> Line: 4439, PID: 2899416
> postgres: logical replication apply worker for subscription 16385
> (ExceptionalCondition+0x69)[0x558b2ac06d41]
> postgres: logical replication apply worker for subscription 16385
> (VirtualXactLockTableCleanup+0xa4)[0x558b2aa9fd74]
> postgres: logical replication apply worker for subscription 16385
> (LockReleaseAll+0xbb)[0x558b2aa9fe7d]
> postgres: logical replication apply worker for subscription 16385
> (+0x4588c6)[0x558b2aa2a8c6]
> postgres: logical replication apply worker for subscription 16385
> (shmem_exit+0x6c)[0x558b2aa87eb1]
> postgres: logical replication apply worker for subscription 16385
> (+0x4b5faa)[0x558b2aa87faa]
> postgres: logical replication apply worker for subscription 16385
> (proc_exit+0xc)[0x558b2aa88031]
> postgres: logical replication apply worker for subscription 16385
> (StartBackgroundWorker+0x147)[0x558b2aa0b4d9]
> postgres: logical replication apply worker for subscription 16385
> (+0x43fdc1)[0x558b2aa11dc1]
> postgres: logical replication apply worker for subscription 16385
> (+0x43ff3d)[0x558b2aa11f3d]
> postgres: logical replication apply worker for subscription 16385
> (+0x440866)[0x558b2aa12866]
> postgres: logical replication apply worker for subscription 16385
> (+0x440e12)[0x558b2aa12e12]
> postgres: logical replication apply worker for subscription 16385
> (BackgroundWorkerInitializeConnection+0x0)[0x558b2aa14396]
> postgres: logical replication apply worker for subscription 16385
> (main+0x21a)[0x558b2a932e21]
>
> I understand, that removing libpqwalreceiver.so (or whole pginst/) is not
> what happens in a production environment every day, but nonetheless it's a
> new failure mode and it can produce many coredumps when testing.
>
> IIUC, that assert will fail in case of any error raised between
> ApplyWorkerMain()->logicalrep_worker_attach()->before_shmem_exit() and
> ApplyWorkerMain()->InitializeApplyWorker()->BackgroundWorkerInitializeC
> onnectionByOid()->InitPostgres().
Thanks for reporting the issue.
I think the problem is that it tried to release locks in
logicalrep_worker_onexit() before the initialization of the process is complete
because this callback function was registered before the init phase. So I think we
can add a conditional statement before releasing locks. Please find an attached
patch.
Best Regards,
Hou zj
Attachments:
[application/octet-stream] 0001-fix-assert-failure-in-logical-replication-apply-work.patch (1.3K, ../../OS0PR01MB57164DF9FC5366024A1952D594659@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-0001-fix-assert-failure-in-logical-replication-apply-work.patch)
download | inline diff:
From a5a11494fdccbfec16ccc56d23dabfab7927a46d Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Wed, 26 Apr 2023 18:12:19 +0800
Subject: [PATCH] Fix assert failure in logical replication apply worker.
The apply worker attempted to release the lock prior to completion of the
process initialization, resulting in an assert failure. To resolve the
issue, the lock is now released only if the apply worker has entered normal
processing mode.
---
src/backend/replication/logical/launcher.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index 970d170e73..447a4ceea7 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -797,8 +797,12 @@ logicalrep_worker_onexit(int code, Datum arg)
* Session level locks may be acquired outside of a transaction in
* parallel apply mode and will not be released when the worker
* terminates, so manually release all locks before the worker exits.
+ *
+ * However, it's not necessary to release locks if the worker hasn't
+ * entered normal mode yet.
*/
- LockReleaseAll(DEFAULT_LOCKMETHOD, true);
+ if (IsNormalProcessingMode())
+ LockReleaseAll(DEFAULT_LOCKMETHOD, true);
ApplyLauncherWakeup();
}
--
2.30.0.windows.2
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
@ 2023-04-26 11:21 ` Amit Kapila <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: Amit Kapila @ 2023-04-26 11:21 UTC (permalink / raw)
To: Zhijie Hou (Fujitsu) <[email protected]>; +Cc: Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>; Masahiko Sawada <[email protected]>
On Wed, Apr 26, 2023 at 4:11 PM Zhijie Hou (Fujitsu)
<[email protected]> wrote:
>
> On Wednesday, April 26, 2023 5:00 PM Alexander Lakhin <[email protected]> wrote:
>
> Thanks for reporting the issue.
>
> I think the problem is that it tried to release locks in
> logicalrep_worker_onexit() before the initialization of the process is complete
> because this callback function was registered before the init phase. So I think we
> can add a conditional statement before releasing locks. Please find an attached
> patch.
>
Yeah, this should work. Yet another possibility is to introduce a new
variable 'InitializingApplyWorker' similar to
'InitializingParallelWorker' and use that to prevent releasing locks.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
@ 2023-04-28 02:51 ` Amit Kapila <[email protected]>
2023-04-28 05:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
1 sibling, 2 replies; 105+ messages in thread
From: Amit Kapila @ 2023-04-28 02:51 UTC (permalink / raw)
To: Zhijie Hou (Fujitsu) <[email protected]>; +Cc: Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>; Masahiko Sawada <[email protected]>
On Wed, Apr 26, 2023 at 4:11 PM Zhijie Hou (Fujitsu)
<[email protected]> wrote:
>
> On Wednesday, April 26, 2023 5:00 PM Alexander Lakhin <[email protected]> wrote:
> >
> > IIUC, that assert will fail in case of any error raised between
> > ApplyWorkerMain()->logicalrep_worker_attach()->before_shmem_exit() and
> > ApplyWorkerMain()->InitializeApplyWorker()->BackgroundWorkerInitializeC
> > onnectionByOid()->InitPostgres().
>
> Thanks for reporting the issue.
>
> I think the problem is that it tried to release locks in
> logicalrep_worker_onexit() before the initialization of the process is complete
> because this callback function was registered before the init phase. So I think we
> can add a conditional statement before releasing locks. Please find an attached
> patch.
>
Alexander, does the proposed patch fix the problem you are facing?
Sawada-San, and others, do you see any better way to fix it than what
has been proposed?
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-04-28 05:00 ` Alexander Lakhin <[email protected]>
1 sibling, 0 replies; 105+ messages in thread
From: Alexander Lakhin @ 2023-04-28 05:00 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; Zhijie Hou (Fujitsu) <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Masahiko Sawada <[email protected]>
Hello Amit and Zhijie,
28.04.2023 05:51, Amit Kapila wrote:
> On Wed, Apr 26, 2023 at 4:11 PM Zhijie Hou (Fujitsu)
> <[email protected]> wrote:
>> I think the problem is that it tried to release locks in
>> logicalrep_worker_onexit() before the initialization of the process is complete
>> because this callback function was registered before the init phase. So I think we
>> can add a conditional statement before releasing locks. Please find an attached
>> patch.
> Alexander, does the proposed patch fix the problem you are facing?
> Sawada-San, and others, do you see any better way to fix it than what
> has been proposed?
Yes, the patch definitely fixes it.
Maybe some other onexit actions can be skipped in the non-normal mode,
but the assert-triggering LockReleaseAll() not called now.
Thank you!
Best regards,
Alexander
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-04-28 06:18 ` Masahiko Sawada <[email protected]>
2023-04-28 09:01 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-02 03:21 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-02 03:35 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
1 sibling, 3 replies; 105+ messages in thread
From: Masahiko Sawada @ 2023-04-28 06:18 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Zhijie Hou (Fujitsu) <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, Apr 28, 2023 at 11:51 AM Amit Kapila <[email protected]> wrote:
>
> On Wed, Apr 26, 2023 at 4:11 PM Zhijie Hou (Fujitsu)
> <[email protected]> wrote:
> >
> > On Wednesday, April 26, 2023 5:00 PM Alexander Lakhin <[email protected]> wrote:
> > >
> > > IIUC, that assert will fail in case of any error raised between
> > > ApplyWorkerMain()->logicalrep_worker_attach()->before_shmem_exit() and
> > > ApplyWorkerMain()->InitializeApplyWorker()->BackgroundWorkerInitializeC
> > > onnectionByOid()->InitPostgres().
> >
> > Thanks for reporting the issue.
> >
> > I think the problem is that it tried to release locks in
> > logicalrep_worker_onexit() before the initialization of the process is complete
> > because this callback function was registered before the init phase. So I think we
> > can add a conditional statement before releasing locks. Please find an attached
> > patch.
> >
>
> Alexander, does the proposed patch fix the problem you are facing?
> Sawada-San, and others, do you see any better way to fix it than what
> has been proposed?
I'm concerned that the idea of relying on IsNormalProcessingMode()
might not be robust since if we change the meaning of
IsNormalProcessingMode() some day it would silently break again. So I
prefer using something like InitializingApplyWorker, or another idea
would be to do cleanup work (e.g., fileset deletion and lock release)
in a separate callback that is registered after connecting to the
database.
While investigating this issue, I've reviewed the code around
callbacks and worker termination etc and I found a problem.
A parallel apply worker calls the before_shmem_exit callbacks in the
following order:
1. ShutdownPostgres()
2. logicalrep_worker_onexit()
3. pa_shutdown()
Since the worker is detached during logicalrep_worker_onexit(),
MyLogicalReplication->leader_pid is an invalid when we call
pa_shutdown():
static void
pa_shutdown(int code, Datum arg)
{
Assert(MyLogicalRepWorker->leader_pid != InvalidPid);
SendProcSignal(MyLogicalRepWorker->leader_pid,
PROCSIG_PARALLEL_APPLY_MESSAGE,
InvalidBackendId);
Also, if the parallel apply worker fails shm_toc_lookup() during the
initialization, it raises an error (because of noError = false) but
ends up a SEGV as MyLogicalRepWorker is still NULL.
I think that we should not use MyLogicalRepWorker->leader_pid in
pa_shutdown() but instead store the leader's pid to a static variable
before registering pa_shutdown() callback. And probably we can
remember the backend id of the leader apply worker to speed up
SendProcSignal().
FWIW, we might need to be careful about the timing when we call
logicalrep_worker_detach() in the worker's termination process. Since
we rely on IsLogicalParallelApplyWorker() for the parallel apply
worker to send ERROR messages to the leader apply worker, if an ERROR
happens after logicalrep_worker_detach(), we will end up with the
assertion failure.
if (IsLogicalParallelApplyWorker())
SendProcSignal(pq_mq_parallel_leader_pid,
PROCSIG_PARALLEL_APPLY_MESSAGE,
pq_mq_parallel_leader_backend_id);
else
{
Assert(IsParallelWorker());
It normally would be a should-no-happen case, though.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-04-28 09:01 ` Amit Kapila <[email protected]>
2023-05-01 03:52 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-04-28 09:01 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: Zhijie Hou (Fujitsu) <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, Apr 28, 2023 at 11:48 AM Masahiko Sawada <[email protected]> wrote:
>
> On Fri, Apr 28, 2023 at 11:51 AM Amit Kapila <[email protected]> wrote:
> >
> > On Wed, Apr 26, 2023 at 4:11 PM Zhijie Hou (Fujitsu)
> > <[email protected]> wrote:
> > >
> > > On Wednesday, April 26, 2023 5:00 PM Alexander Lakhin <[email protected]> wrote:
> > > >
> > > > IIUC, that assert will fail in case of any error raised between
> > > > ApplyWorkerMain()->logicalrep_worker_attach()->before_shmem_exit() and
> > > > ApplyWorkerMain()->InitializeApplyWorker()->BackgroundWorkerInitializeC
> > > > onnectionByOid()->InitPostgres().
> > >
> > > Thanks for reporting the issue.
> > >
> > > I think the problem is that it tried to release locks in
> > > logicalrep_worker_onexit() before the initialization of the process is complete
> > > because this callback function was registered before the init phase. So I think we
> > > can add a conditional statement before releasing locks. Please find an attached
> > > patch.
> > >
> >
> > Alexander, does the proposed patch fix the problem you are facing?
> > Sawada-San, and others, do you see any better way to fix it than what
> > has been proposed?
>
> I'm concerned that the idea of relying on IsNormalProcessingMode()
> might not be robust since if we change the meaning of
> IsNormalProcessingMode() some day it would silently break again. So I
> prefer using something like InitializingApplyWorker,
>
I think if we change the meaning of IsNormalProcessingMode() then it
could also break the other places the similar check is being used.
However, I am fine with InitializingApplyWorker as that could be used
at other places as well. I just want to avoid adding another variable
by using IsNormalProcessingMode.
> or another idea
> would be to do cleanup work (e.g., fileset deletion and lock release)
> in a separate callback that is registered after connecting to the
> database.
>
Yeah, but not sure if it's worth having multiple callbacks for cleanup work.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-28 09:01 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-05-01 03:52 ` Masahiko Sawada <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: Masahiko Sawada @ 2023-05-01 03:52 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Zhijie Hou (Fujitsu) <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, Apr 28, 2023 at 6:01 PM Amit Kapila <[email protected]> wrote:
>
> On Fri, Apr 28, 2023 at 11:48 AM Masahiko Sawada <[email protected]> wrote:
> >
> > On Fri, Apr 28, 2023 at 11:51 AM Amit Kapila <[email protected]> wrote:
> > >
> > > On Wed, Apr 26, 2023 at 4:11 PM Zhijie Hou (Fujitsu)
> > > <[email protected]> wrote:
> > > >
> > > > On Wednesday, April 26, 2023 5:00 PM Alexander Lakhin <[email protected]> wrote:
> > > > >
> > > > > IIUC, that assert will fail in case of any error raised between
> > > > > ApplyWorkerMain()->logicalrep_worker_attach()->before_shmem_exit() and
> > > > > ApplyWorkerMain()->InitializeApplyWorker()->BackgroundWorkerInitializeC
> > > > > onnectionByOid()->InitPostgres().
> > > >
> > > > Thanks for reporting the issue.
> > > >
> > > > I think the problem is that it tried to release locks in
> > > > logicalrep_worker_onexit() before the initialization of the process is complete
> > > > because this callback function was registered before the init phase. So I think we
> > > > can add a conditional statement before releasing locks. Please find an attached
> > > > patch.
> > > >
> > >
> > > Alexander, does the proposed patch fix the problem you are facing?
> > > Sawada-San, and others, do you see any better way to fix it than what
> > > has been proposed?
> >
> > I'm concerned that the idea of relying on IsNormalProcessingMode()
> > might not be robust since if we change the meaning of
> > IsNormalProcessingMode() some day it would silently break again. So I
> > prefer using something like InitializingApplyWorker,
> >
>
> I think if we change the meaning of IsNormalProcessingMode() then it
> could also break the other places the similar check is being used.
Right, but I think it's unclear the relationship between the
processing modes and releasing session locks. If non-normal-processing
mode means we're still in the process initialization phase, why we
don't skip other cleanup works such as walrcv_disconnect() and
FileSetDeleteAll()?
> However, I am fine with InitializingApplyWorker as that could be used
> at other places as well. I just want to avoid adding another variable
> by using IsNormalProcessingMode.
I think it's less confusing.
>
> > or another idea
> > would be to do cleanup work (e.g., fileset deletion and lock release)
> > in a separate callback that is registered after connecting to the
> > database.
> >
>
> Yeah, but not sure if it's worth having multiple callbacks for cleanup work.
Fair point.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-05-02 03:21 ` Amit Kapila <[email protected]>
2023-05-08 03:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-05-02 03:21 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: Zhijie Hou (Fujitsu) <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, Apr 28, 2023 at 11:48 AM Masahiko Sawada <[email protected]> wrote:
>
> While investigating this issue, I've reviewed the code around
> callbacks and worker termination etc and I found a problem.
>
> A parallel apply worker calls the before_shmem_exit callbacks in the
> following order:
>
> 1. ShutdownPostgres()
> 2. logicalrep_worker_onexit()
> 3. pa_shutdown()
>
> Since the worker is detached during logicalrep_worker_onexit(),
> MyLogicalReplication->leader_pid is an invalid when we call
> pa_shutdown():
>
> static void
> pa_shutdown(int code, Datum arg)
> {
> Assert(MyLogicalRepWorker->leader_pid != InvalidPid);
> SendProcSignal(MyLogicalRepWorker->leader_pid,
> PROCSIG_PARALLEL_APPLY_MESSAGE,
> InvalidBackendId);
>
> Also, if the parallel apply worker fails shm_toc_lookup() during the
> initialization, it raises an error (because of noError = false) but
> ends up a SEGV as MyLogicalRepWorker is still NULL.
>
> I think that we should not use MyLogicalRepWorker->leader_pid in
> pa_shutdown() but instead store the leader's pid to a static variable
> before registering pa_shutdown() callback.
>
Why not simply move the registration of pa_shutdown() to someplace
after logicalrep_worker_attach()? BTW, it seems we don't have access
to MyLogicalRepWorker->leader_pid till we attach to the worker slot
via logicalrep_worker_attach(), so we anyway need to do what you are
suggesting after attaching to the worker slot.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:21 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-05-08 03:07 ` Masahiko Sawada <[email protected]>
2023-05-08 03:52 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Masahiko Sawada @ 2023-05-08 03:07 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Zhijie Hou (Fujitsu) <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Tue, May 2, 2023 at 12:22 PM Amit Kapila <[email protected]> wrote:
>
> On Fri, Apr 28, 2023 at 11:48 AM Masahiko Sawada <[email protected]> wrote:
> >
> > While investigating this issue, I've reviewed the code around
> > callbacks and worker termination etc and I found a problem.
> >
> > A parallel apply worker calls the before_shmem_exit callbacks in the
> > following order:
> >
> > 1. ShutdownPostgres()
> > 2. logicalrep_worker_onexit()
> > 3. pa_shutdown()
> >
> > Since the worker is detached during logicalrep_worker_onexit(),
> > MyLogicalReplication->leader_pid is an invalid when we call
> > pa_shutdown():
> >
> > static void
> > pa_shutdown(int code, Datum arg)
> > {
> > Assert(MyLogicalRepWorker->leader_pid != InvalidPid);
> > SendProcSignal(MyLogicalRepWorker->leader_pid,
> > PROCSIG_PARALLEL_APPLY_MESSAGE,
> > InvalidBackendId);
> >
> > Also, if the parallel apply worker fails shm_toc_lookup() during the
> > initialization, it raises an error (because of noError = false) but
> > ends up a SEGV as MyLogicalRepWorker is still NULL.
> >
> > I think that we should not use MyLogicalRepWorker->leader_pid in
> > pa_shutdown() but instead store the leader's pid to a static variable
> > before registering pa_shutdown() callback.
> >
>
> Why not simply move the registration of pa_shutdown() to someplace
> after logicalrep_worker_attach()?
If we do that, the worker won't call dsm_detach() if it raises an
ERROR in logicalrep_worker_attach(), is that okay? It seems that it's
no practically problem since we call dsm_backend_shutdown() in
shmem_exit(), but if so why do we need to call it in pa_shutdown()?
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:21 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-08 03:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-05-08 03:52 ` Zhijie Hou (Fujitsu) <[email protected]>
2023-05-08 05:38 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Zhijie Hou (Fujitsu) @ 2023-05-08 03:52 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; Amit Kapila <[email protected]>; +Cc: Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Monday, May 8, 2023 11:08 AM Masahiko Sawada <[email protected]>
Hi,
>
> On Tue, May 2, 2023 at 12:22 PM Amit Kapila <[email protected]>
> wrote:
> >
> > On Fri, Apr 28, 2023 at 11:48 AM Masahiko Sawada
> <[email protected]> wrote:
> > >
> > > While investigating this issue, I've reviewed the code around
> > > callbacks and worker termination etc and I found a problem.
> > >
> > > A parallel apply worker calls the before_shmem_exit callbacks in the
> > > following order:
> > >
> > > 1. ShutdownPostgres()
> > > 2. logicalrep_worker_onexit()
> > > 3. pa_shutdown()
> > >
> > > Since the worker is detached during logicalrep_worker_onexit(),
> > > MyLogicalReplication->leader_pid is an invalid when we call
> > > pa_shutdown():
> > >
> > > static void
> > > pa_shutdown(int code, Datum arg)
> > > {
> > > Assert(MyLogicalRepWorker->leader_pid != InvalidPid);
> > > SendProcSignal(MyLogicalRepWorker->leader_pid,
> > > PROCSIG_PARALLEL_APPLY_MESSAGE,
> > > InvalidBackendId);
> > >
> > > Also, if the parallel apply worker fails shm_toc_lookup() during the
> > > initialization, it raises an error (because of noError = false) but
> > > ends up a SEGV as MyLogicalRepWorker is still NULL.
> > >
> > > I think that we should not use MyLogicalRepWorker->leader_pid in
> > > pa_shutdown() but instead store the leader's pid to a static variable
> > > before registering pa_shutdown() callback.
> > >
> >
> > Why not simply move the registration of pa_shutdown() to someplace
> > after logicalrep_worker_attach()?
>
> If we do that, the worker won't call dsm_detach() if it raises an
> ERROR in logicalrep_worker_attach(), is that okay? It seems that it's
> no practically problem since we call dsm_backend_shutdown() in
> shmem_exit(), but if so why do we need to call it in pa_shutdown()?
I think the dsm_detach in pa_shutdown was intended to fire on_dsm_detach
callbacks to give callback a chance to report stat before the stat system is
shutdown, following what we do in ParallelWorkerShutdown() (e.g.
sharedfileset.c callbacks cause fd.c to do ReportTemporaryFileUsage(), so we
need to fire that earlier).
But for parallel apply, we currently only have one on_dsm_detach
callback(shm_mq_detach_callback) which doesn't report extra stats. So the
dsm_detach in pa_shutdown is only used to make it a bit future-proof in case
we add some other on_dsm_detach callbacks in the future which need to report
stats.
Best regards,
Hou zj
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:21 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-08 03:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-08 03:52 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
@ 2023-05-08 05:38 ` Masahiko Sawada <[email protected]>
2023-05-08 06:33 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Masahiko Sawada @ 2023-05-08 05:38 UTC (permalink / raw)
To: Zhijie Hou (Fujitsu) <[email protected]>; +Cc: Amit Kapila <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Mon, May 8, 2023 at 12:52 PM Zhijie Hou (Fujitsu)
<[email protected]> wrote:
>
> On Monday, May 8, 2023 11:08 AM Masahiko Sawada <[email protected]>
>
> Hi,
>
> >
> > On Tue, May 2, 2023 at 12:22 PM Amit Kapila <[email protected]>
> > wrote:
> > >
> > > On Fri, Apr 28, 2023 at 11:48 AM Masahiko Sawada
> > <[email protected]> wrote:
> > > >
> > > > While investigating this issue, I've reviewed the code around
> > > > callbacks and worker termination etc and I found a problem.
> > > >
> > > > A parallel apply worker calls the before_shmem_exit callbacks in the
> > > > following order:
> > > >
> > > > 1. ShutdownPostgres()
> > > > 2. logicalrep_worker_onexit()
> > > > 3. pa_shutdown()
> > > >
> > > > Since the worker is detached during logicalrep_worker_onexit(),
> > > > MyLogicalReplication->leader_pid is an invalid when we call
> > > > pa_shutdown():
> > > >
> > > > static void
> > > > pa_shutdown(int code, Datum arg)
> > > > {
> > > > Assert(MyLogicalRepWorker->leader_pid != InvalidPid);
> > > > SendProcSignal(MyLogicalRepWorker->leader_pid,
> > > > PROCSIG_PARALLEL_APPLY_MESSAGE,
> > > > InvalidBackendId);
> > > >
> > > > Also, if the parallel apply worker fails shm_toc_lookup() during the
> > > > initialization, it raises an error (because of noError = false) but
> > > > ends up a SEGV as MyLogicalRepWorker is still NULL.
> > > >
> > > > I think that we should not use MyLogicalRepWorker->leader_pid in
> > > > pa_shutdown() but instead store the leader's pid to a static variable
> > > > before registering pa_shutdown() callback.
> > > >
> > >
> > > Why not simply move the registration of pa_shutdown() to someplace
> > > after logicalrep_worker_attach()?
> >
> > If we do that, the worker won't call dsm_detach() if it raises an
> > ERROR in logicalrep_worker_attach(), is that okay? It seems that it's
> > no practically problem since we call dsm_backend_shutdown() in
> > shmem_exit(), but if so why do we need to call it in pa_shutdown()?
>
> I think the dsm_detach in pa_shutdown was intended to fire on_dsm_detach
> callbacks to give callback a chance to report stat before the stat system is
> shutdown, following what we do in ParallelWorkerShutdown() (e.g.
> sharedfileset.c callbacks cause fd.c to do ReportTemporaryFileUsage(), so we
> need to fire that earlier).
>
> But for parallel apply, we currently only have one on_dsm_detach
> callback(shm_mq_detach_callback) which doesn't report extra stats. So the
> dsm_detach in pa_shutdown is only used to make it a bit future-proof in case
> we add some other on_dsm_detach callbacks in the future which need to report
> stats.
Make sense . Given that it's possible that we add other callbacks that
report stats in the future, I think it's better not to move the
position to register pa_shutdown() callback.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:21 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-08 03:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-08 03:52 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-05-08 05:38 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-05-08 06:33 ` Amit Kapila <[email protected]>
2023-05-09 02:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-05-08 06:33 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; +Cc: Zhijie Hou (Fujitsu) <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Mon, May 8, 2023 at 11:08 AM Masahiko Sawada <[email protected]> wrote:
>
> On Mon, May 8, 2023 at 12:52 PM Zhijie Hou (Fujitsu)
> <[email protected]> wrote:
> >
> > On Monday, May 8, 2023 11:08 AM Masahiko Sawada <[email protected]>
> >
> > Hi,
> >
> > >
> > > On Tue, May 2, 2023 at 12:22 PM Amit Kapila <[email protected]>
> > > wrote:
> > > >
> > > > On Fri, Apr 28, 2023 at 11:48 AM Masahiko Sawada
> > > <[email protected]> wrote:
> > > > >
> > > > > While investigating this issue, I've reviewed the code around
> > > > > callbacks and worker termination etc and I found a problem.
> > > > >
> > > > > A parallel apply worker calls the before_shmem_exit callbacks in the
> > > > > following order:
> > > > >
> > > > > 1. ShutdownPostgres()
> > > > > 2. logicalrep_worker_onexit()
> > > > > 3. pa_shutdown()
> > > > >
> > > > > Since the worker is detached during logicalrep_worker_onexit(),
> > > > > MyLogicalReplication->leader_pid is an invalid when we call
> > > > > pa_shutdown():
> > > > >
> > > > > static void
> > > > > pa_shutdown(int code, Datum arg)
> > > > > {
> > > > > Assert(MyLogicalRepWorker->leader_pid != InvalidPid);
> > > > > SendProcSignal(MyLogicalRepWorker->leader_pid,
> > > > > PROCSIG_PARALLEL_APPLY_MESSAGE,
> > > > > InvalidBackendId);
> > > > >
> > > > > Also, if the parallel apply worker fails shm_toc_lookup() during the
> > > > > initialization, it raises an error (because of noError = false) but
> > > > > ends up a SEGV as MyLogicalRepWorker is still NULL.
> > > > >
> > > > > I think that we should not use MyLogicalRepWorker->leader_pid in
> > > > > pa_shutdown() but instead store the leader's pid to a static variable
> > > > > before registering pa_shutdown() callback.
> > > > >
> > > >
> > > > Why not simply move the registration of pa_shutdown() to someplace
> > > > after logicalrep_worker_attach()?
> > >
> > > If we do that, the worker won't call dsm_detach() if it raises an
> > > ERROR in logicalrep_worker_attach(), is that okay? It seems that it's
> > > no practically problem since we call dsm_backend_shutdown() in
> > > shmem_exit(), but if so why do we need to call it in pa_shutdown()?
> >
> > I think the dsm_detach in pa_shutdown was intended to fire on_dsm_detach
> > callbacks to give callback a chance to report stat before the stat system is
> > shutdown, following what we do in ParallelWorkerShutdown() (e.g.
> > sharedfileset.c callbacks cause fd.c to do ReportTemporaryFileUsage(), so we
> > need to fire that earlier).
> >
> > But for parallel apply, we currently only have one on_dsm_detach
> > callback(shm_mq_detach_callback) which doesn't report extra stats. So the
> > dsm_detach in pa_shutdown is only used to make it a bit future-proof in case
> > we add some other on_dsm_detach callbacks in the future which need to report
> > stats.
>
> Make sense . Given that it's possible that we add other callbacks that
> report stats in the future, I think it's better not to move the
> position to register pa_shutdown() callback.
>
Hmm, what kind of stats do we expect to be collected before we
register pa_shutdown? I think if required we can register such a
callback after pa_shutdown. I feel without reordering the callbacks,
the fix would be a bit complicated as explained in my previous email,
so I don't think it is worth complicating this code unless really
required.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:21 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-08 03:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-08 03:52 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-05-08 05:38 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-08 06:33 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-05-09 02:19 ` Masahiko Sawada <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: Masahiko Sawada @ 2023-05-09 02:19 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Zhijie Hou (Fujitsu) <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Mon, May 8, 2023 at 3:34 PM Amit Kapila <[email protected]> wrote:
>
> On Mon, May 8, 2023 at 11:08 AM Masahiko Sawada <[email protected]> wrote:
> >
> > On Mon, May 8, 2023 at 12:52 PM Zhijie Hou (Fujitsu)
> > <[email protected]> wrote:
> > >
> > > On Monday, May 8, 2023 11:08 AM Masahiko Sawada <[email protected]>
> > >
> > > Hi,
> > >
> > > >
> > > > On Tue, May 2, 2023 at 12:22 PM Amit Kapila <[email protected]>
> > > > wrote:
> > > > >
> > > > > On Fri, Apr 28, 2023 at 11:48 AM Masahiko Sawada
> > > > <[email protected]> wrote:
> > > > > >
> > > > > > While investigating this issue, I've reviewed the code around
> > > > > > callbacks and worker termination etc and I found a problem.
> > > > > >
> > > > > > A parallel apply worker calls the before_shmem_exit callbacks in the
> > > > > > following order:
> > > > > >
> > > > > > 1. ShutdownPostgres()
> > > > > > 2. logicalrep_worker_onexit()
> > > > > > 3. pa_shutdown()
> > > > > >
> > > > > > Since the worker is detached during logicalrep_worker_onexit(),
> > > > > > MyLogicalReplication->leader_pid is an invalid when we call
> > > > > > pa_shutdown():
> > > > > >
> > > > > > static void
> > > > > > pa_shutdown(int code, Datum arg)
> > > > > > {
> > > > > > Assert(MyLogicalRepWorker->leader_pid != InvalidPid);
> > > > > > SendProcSignal(MyLogicalRepWorker->leader_pid,
> > > > > > PROCSIG_PARALLEL_APPLY_MESSAGE,
> > > > > > InvalidBackendId);
> > > > > >
> > > > > > Also, if the parallel apply worker fails shm_toc_lookup() during the
> > > > > > initialization, it raises an error (because of noError = false) but
> > > > > > ends up a SEGV as MyLogicalRepWorker is still NULL.
> > > > > >
> > > > > > I think that we should not use MyLogicalRepWorker->leader_pid in
> > > > > > pa_shutdown() but instead store the leader's pid to a static variable
> > > > > > before registering pa_shutdown() callback.
> > > > > >
> > > > >
> > > > > Why not simply move the registration of pa_shutdown() to someplace
> > > > > after logicalrep_worker_attach()?
> > > >
> > > > If we do that, the worker won't call dsm_detach() if it raises an
> > > > ERROR in logicalrep_worker_attach(), is that okay? It seems that it's
> > > > no practically problem since we call dsm_backend_shutdown() in
> > > > shmem_exit(), but if so why do we need to call it in pa_shutdown()?
> > >
> > > I think the dsm_detach in pa_shutdown was intended to fire on_dsm_detach
> > > callbacks to give callback a chance to report stat before the stat system is
> > > shutdown, following what we do in ParallelWorkerShutdown() (e.g.
> > > sharedfileset.c callbacks cause fd.c to do ReportTemporaryFileUsage(), so we
> > > need to fire that earlier).
> > >
> > > But for parallel apply, we currently only have one on_dsm_detach
> > > callback(shm_mq_detach_callback) which doesn't report extra stats. So the
> > > dsm_detach in pa_shutdown is only used to make it a bit future-proof in case
> > > we add some other on_dsm_detach callbacks in the future which need to report
> > > stats.
> >
> > Make sense . Given that it's possible that we add other callbacks that
> > report stats in the future, I think it's better not to move the
> > position to register pa_shutdown() callback.
> >
>
> Hmm, what kind of stats do we expect to be collected before we
> register pa_shutdown? I think if required we can register such a
> callback after pa_shutdown. I feel without reordering the callbacks,
> the fix would be a bit complicated as explained in my previous email,
> so I don't think it is worth complicating this code unless really
> required.
Fair point. I agree that the issue can be resolved by carefully
ordering the callback registration.
Another thing I'm concerned about is that since both the leader worker
and parallel worker detach DSM before logicalrep_worker_onexit(),
cleaning up work that touches DSM cannot be done in
logicalrep_worker_onexit(). If we need to do something in the future,
we would need to have another callback called before detaching DSM.
But I'm fine as it's not a problem for now.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
@ 2023-05-02 03:35 ` Zhijie Hou (Fujitsu) <[email protected]>
2023-05-02 04:16 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2 siblings, 1 reply; 105+ messages in thread
From: Zhijie Hou (Fujitsu) @ 2023-05-02 03:35 UTC (permalink / raw)
To: Masahiko Sawada <[email protected]>; Amit Kapila <[email protected]>; +Cc: Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Friday, April 28, 2023 2:18 PM Masahiko Sawada <[email protected]> wrote:
>
> On Fri, Apr 28, 2023 at 11:51 AM Amit Kapila <[email protected]> wrote:
> >
> > On Wed, Apr 26, 2023 at 4:11 PM Zhijie Hou (Fujitsu)
> > <[email protected]> wrote:
> > >
> > > On Wednesday, April 26, 2023 5:00 PM Alexander Lakhin
> <[email protected]> wrote:
> > > >
> > > > IIUC, that assert will fail in case of any error raised between
> > > >
> ApplyWorkerMain()->logicalrep_worker_attach()->before_shmem_exit() and
> > > >
> ApplyWorkerMain()->InitializeApplyWorker()->BackgroundWorkerInitializeC
> > > > onnectionByOid()->InitPostgres().
> > >
> > > Thanks for reporting the issue.
> > >
> > > I think the problem is that it tried to release locks in
> > > logicalrep_worker_onexit() before the initialization of the process is
> complete
> > > because this callback function was registered before the init phase. So I
> think we
> > > can add a conditional statement before releasing locks. Please find an
> attached
> > > patch.
> > >
> >
> > Alexander, does the proposed patch fix the problem you are facing?
> > Sawada-San, and others, do you see any better way to fix it than what
> > has been proposed?
>
> I'm concerned that the idea of relying on IsNormalProcessingMode()
> might not be robust since if we change the meaning of
> IsNormalProcessingMode() some day it would silently break again. So I
> prefer using something like InitializingApplyWorker, or another idea
> would be to do cleanup work (e.g., fileset deletion and lock release)
> in a separate callback that is registered after connecting to the
> database.
Thanks for the review. I agree that it’s better to use a new variable here.
Attach the patch for the same.
>
> FWIW, we might need to be careful about the timing when we call
> logicalrep_worker_detach() in the worker's termination process. Since
> we rely on IsLogicalParallelApplyWorker() for the parallel apply
> worker to send ERROR messages to the leader apply worker, if an ERROR
> happens after logicalrep_worker_detach(), we will end up with the
> assertion failure.
>
> if (IsLogicalParallelApplyWorker())
> SendProcSignal(pq_mq_parallel_leader_pid,
> PROCSIG_PARALLEL_APPLY_MESSAGE,
> pq_mq_parallel_leader_backend_id);
> else
> {
> Assert(IsParallelWorker());
>
> It normally would be a should-no-happen case, though.
Yes, I think currently PA sends ERROR message before exiting,
so the callback functions are always fired after the above code which
looks fine to me.
Best Regards,
Hou zj
Attachments:
[application/octet-stream] v2-0001-Fix-assert-failure-in-logical-replication-apply-w.patch (4.0K, ../../OS0PR01MB5716E3C106DF49B3056EF72C946F9@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-v2-0001-Fix-assert-failure-in-logical-replication-apply-w.patch)
download | inline diff:
From b1e89a45aee2de464c710acc76f19f72fc92f1c6 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Wed, 26 Apr 2023 18:12:19 +0800
Subject: [PATCH v2 1/2] Fix assert failure in logical replication apply
worker.
The apply worker attempted to release the lock prior to completion of the
process initialization, resulting in an assert failure. To resolve the
issue, the lock is now released only if the apply worker has finished
the initialization phase.
---
src/backend/replication/logical/applyparallelworker.c | 4 ++++
src/backend/replication/logical/launcher.c | 6 +++++-
src/backend/replication/logical/worker.c | 7 +++++++
src/include/replication/worker_internal.h | 2 ++
4 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 4518683779..ee7a18137f 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -873,6 +873,8 @@ ParallelApplyWorkerMain(Datum main_arg)
int worker_slot = DatumGetInt32(main_arg);
char originname[NAMEDATALEN];
+ InitializingApplyWorker = true;
+
/* Setup signal handling. */
pqsignal(SIGHUP, SignalHandlerForConfigReload);
pqsignal(SIGINT, SignalHandlerForShutdownRequest);
@@ -940,6 +942,8 @@ ParallelApplyWorkerMain(Datum main_arg)
InitializeApplyWorker();
+ InitializingApplyWorker = false;
+
/* Setup replication origin tracking. */
StartTransactionCommand();
ReplicationOriginNameForLogicalRep(MySubscription->oid, InvalidOid,
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index 970d170e73..70265b7fd6 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -797,8 +797,12 @@ logicalrep_worker_onexit(int code, Datum arg)
* Session level locks may be acquired outside of a transaction in
* parallel apply mode and will not be released when the worker
* terminates, so manually release all locks before the worker exits.
+ *
+ * However, if the worker is being initialized, there is no need to release
+ * locks.
*/
- LockReleaseAll(DEFAULT_LOCKMETHOD, true);
+ if (!InitializingApplyWorker)
+ LockReleaseAll(DEFAULT_LOCKMETHOD, true);
ApplyLauncherWakeup();
}
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index dbf88c9553..879309b316 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -331,6 +331,9 @@ static TransactionId stream_xid = InvalidTransactionId;
*/
static uint32 parallel_stream_nchanges = 0;
+/* Are we initializing a apply worker? */
+bool InitializingApplyWorker = false;
+
/*
* We enable skipping all data modification changes (INSERT, UPDATE, etc.) for
* the subscription if the remote transaction's finish LSN matches the subskiplsn.
@@ -4526,6 +4529,8 @@ ApplyWorkerMain(Datum main_arg)
WalRcvStreamOptions options;
int server_version;
+ InitializingApplyWorker = true;
+
/* Attach to slot */
logicalrep_worker_attach(worker_slot);
@@ -4548,6 +4553,8 @@ ApplyWorkerMain(Datum main_arg)
InitializeApplyWorker();
+ InitializingApplyWorker = false;
+
/* Connect to the origin and start the replication. */
elog(DEBUG1, "connecting to publisher using connection string \"%s\"",
MySubscription->conninfo);
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index dce71d2c50..b57eed052f 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -225,6 +225,8 @@ extern PGDLLIMPORT LogicalRepWorker *MyLogicalRepWorker;
extern PGDLLIMPORT bool in_remote_transaction;
+extern PGDLLIMPORT bool InitializingApplyWorker;
+
extern void logicalrep_worker_attach(int slot);
extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
bool only_running);
--
2.30.0.windows.2
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:35 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
@ 2023-05-02 04:16 ` Amit Kapila <[email protected]>
2023-05-03 07:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-05-02 04:16 UTC (permalink / raw)
To: Zhijie Hou (Fujitsu) <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Tue, May 2, 2023 at 9:06 AM Zhijie Hou (Fujitsu)
<[email protected]> wrote:
>
> On Friday, April 28, 2023 2:18 PM Masahiko Sawada <[email protected]> wrote:
> >
> > >
> > > Alexander, does the proposed patch fix the problem you are facing?
> > > Sawada-San, and others, do you see any better way to fix it than what
> > > has been proposed?
> >
> > I'm concerned that the idea of relying on IsNormalProcessingMode()
> > might not be robust since if we change the meaning of
> > IsNormalProcessingMode() some day it would silently break again. So I
> > prefer using something like InitializingApplyWorker, or another idea
> > would be to do cleanup work (e.g., fileset deletion and lock release)
> > in a separate callback that is registered after connecting to the
> > database.
>
> Thanks for the review. I agree that it’s better to use a new variable here.
> Attach the patch for the same.
>
+ *
+ * However, if the worker is being initialized, there is no need to release
+ * locks.
*/
- LockReleaseAll(DEFAULT_LOCKMETHOD, true);
+ if (!InitializingApplyWorker)
+ LockReleaseAll(DEFAULT_LOCKMETHOD, true);
Can we slightly reword this comment as: "The locks will be acquired
once the worker is initialized."?
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:35 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-05-02 04:16 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-05-03 07:17 ` Amit Kapila <[email protected]>
2023-05-05 03:44 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-05-03 07:17 UTC (permalink / raw)
To: Zhijie Hou (Fujitsu) <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Tue, May 2, 2023 at 9:46 AM Amit Kapila <[email protected]> wrote:
>
> On Tue, May 2, 2023 at 9:06 AM Zhijie Hou (Fujitsu)
> <[email protected]> wrote:
> >
> > On Friday, April 28, 2023 2:18 PM Masahiko Sawada <[email protected]> wrote:
> > >
> > > >
> > > > Alexander, does the proposed patch fix the problem you are facing?
> > > > Sawada-San, and others, do you see any better way to fix it than what
> > > > has been proposed?
> > >
> > > I'm concerned that the idea of relying on IsNormalProcessingMode()
> > > might not be robust since if we change the meaning of
> > > IsNormalProcessingMode() some day it would silently break again. So I
> > > prefer using something like InitializingApplyWorker, or another idea
> > > would be to do cleanup work (e.g., fileset deletion and lock release)
> > > in a separate callback that is registered after connecting to the
> > > database.
> >
> > Thanks for the review. I agree that it’s better to use a new variable here.
> > Attach the patch for the same.
> >
>
> + *
> + * However, if the worker is being initialized, there is no need to release
> + * locks.
> */
> - LockReleaseAll(DEFAULT_LOCKMETHOD, true);
> + if (!InitializingApplyWorker)
> + LockReleaseAll(DEFAULT_LOCKMETHOD, true);
>
> Can we slightly reword this comment as: "The locks will be acquired
> once the worker is initialized."?
>
After making this modification, I pushed your patch. Thanks!
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 105+ messages in thread
* RE: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:35 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-05-02 04:16 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-03 07:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-05-05 03:44 ` Zhijie Hou (Fujitsu) <[email protected]>
2023-05-08 11:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Zhijie Hou (Fujitsu) @ 2023-05-05 03:44 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Wednesday, May 3, 2023 3:17 PM Amit Kapila <[email protected]> wrote:
>
> On Tue, May 2, 2023 at 9:46 AM Amit Kapila <[email protected]>
> wrote:
> >
> > On Tue, May 2, 2023 at 9:06 AM Zhijie Hou (Fujitsu)
> > <[email protected]> wrote:
> > >
> > > On Friday, April 28, 2023 2:18 PM Masahiko Sawada
> <[email protected]> wrote:
> > > >
> > > > >
> > > > > Alexander, does the proposed patch fix the problem you are facing?
> > > > > Sawada-San, and others, do you see any better way to fix it than
> > > > > what has been proposed?
> > > >
> > > > I'm concerned that the idea of relying on IsNormalProcessingMode()
> > > > might not be robust since if we change the meaning of
> > > > IsNormalProcessingMode() some day it would silently break again.
> > > > So I prefer using something like InitializingApplyWorker, or
> > > > another idea would be to do cleanup work (e.g., fileset deletion
> > > > and lock release) in a separate callback that is registered after
> > > > connecting to the database.
> > >
> > > Thanks for the review. I agree that it’s better to use a new variable here.
> > > Attach the patch for the same.
> > >
> >
> > + *
> > + * However, if the worker is being initialized, there is no need to
> > + release
> > + * locks.
> > */
> > - LockReleaseAll(DEFAULT_LOCKMETHOD, true);
> > + if (!InitializingApplyWorker)
> > + LockReleaseAll(DEFAULT_LOCKMETHOD, true);
> >
> > Can we slightly reword this comment as: "The locks will be acquired
> > once the worker is initialized."?
> >
>
> After making this modification, I pushed your patch. Thanks!
Thanks for pushing.
Attach another patch to fix the problem that pa_shutdown will access invalid
MyLogicalRepWorker. I personally want to avoid introducing new static variable,
so I only reorder the callback registration in this version.
When testing this, I notice a rare case that the leader is possible to receive
the worker termination message after the leader stops the parallel worker. This
is unnecessary and have a risk that the leader would try to access the detached
memory queue. This is more likely to happen and sometimes cause the failure in
regression tests after the registration reorder patch because the dsm is
detached earlier after applying the patch.
So, put the patch that detach the error queue before stopping worker as 0001
and the registration reorder patch as 0002.
Best Regards,
Hou zj
Attachments:
[application/octet-stream] 0002-adjust-the-order-of-callback-registration-to-avoid-a.patch (2.8K, ../../OS0PR01MB57161176B8DB0A662D6F053D94729@OS0PR01MB5716.jpnprd01.prod.outlook.com/2-0002-adjust-the-order-of-callback-registration-to-avoid-a.patch)
download | inline diff:
From fc0824a5580b00ce685d91964a8193527f62d908 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <[email protected]>
Date: Fri, 28 Apr 2023 15:50:04 +0800
Subject: [PATCH 2/2] adjust the order of callback registration to avoid
accessing invalid memory
The callback function pa_shutdown(), which accesses MyLogicalRepWorker
internally, was registered before initialization of MyLogicalRepWorker. As a
result, if an ERROR occurs before initialization completes, pa_shutdown() will
attempt to access invalid memory. Additionally, pa_shutdown() was registered
before an exit callback function that resets MyLogicalRepWorker. If an ERROR
occurs later, pa_shutdown() will be invoked after the reset, potentially
leading to incorrect information.
To fix this, reorder the registration process, so that pa_shutdown() is
registered after the initialization and other exit callback function.
While on it, add few comments atop pa_shutdown to enhance code readability.
---
.../replication/logical/applyparallelworker.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index c79765ce20..1bfb7ee06d 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -836,6 +836,9 @@ LogicalParallelApplyLoop(shm_mq_handle *mqh)
* Make sure the leader apply worker tries to read from our error queue one more
* time. This guards against the case where we exit uncleanly without sending
* an ErrorResponse, for example because some code calls proc_exit directly.
+ *
+ * Also explicitly detach from dsm segment to fire on_dsm_detach callbacks. See
+ * ParallelWorkerShutdown for details.
*/
static void
pa_shutdown(int code, Datum arg)
@@ -892,8 +895,6 @@ ParallelApplyWorkerMain(Datum main_arg)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("bad magic number in dynamic shared memory segment")));
- before_shmem_exit(pa_shutdown, PointerGetDatum(seg));
-
/* Look up the shared information. */
shared = shm_toc_lookup(toc, PARALLEL_APPLY_KEY_SHARED, false);
MyParallelShared = shared;
@@ -912,6 +913,13 @@ ParallelApplyWorkerMain(Datum main_arg)
*/
logicalrep_worker_attach(worker_slot);
+ /*
+ * Register the callback after attaching to the worker slot to ensure it is
+ * invoked after MyLogicalRepWorker is initialized but before detaching
+ * from the slot. This ensures that MyLogicalRepWorker remains valid.
+ */
+ before_shmem_exit(pa_shutdown, PointerGetDatum(seg));
+
SpinLockAcquire(&MyParallelShared->mutex);
MyParallelShared->logicalrep_worker_generation = MyLogicalRepWorker->generation;
MyParallelShared->logicalrep_worker_slot_no = worker_slot;
--
2.30.0.windows.2
[application/octet-stream] 0001-Detach-the-error-queue-before-stopping-parallel-appl.patch (3.7K, ../../OS0PR01MB57161176B8DB0A662D6F053D94729@OS0PR01MB5716.jpnprd01.prod.outlook.com/3-0001-Detach-the-error-queue-before-stopping-parallel-appl.patch)
download | inline diff:
From c188075f07e5dcfa53a77c92b25913af31622e54 Mon Sep 17 00:00:00 2001
From: sherlockcpp <[email protected]>
Date: Sun, 30 Apr 2023 20:58:42 +0800
Subject: [PATCH 1/2] Detach the error queue before stopping parallel apply
worker
Detach from the error_mq_handle for the parallel apply worker before
terminating it. This prevents the leader apply worker from receiving the
worker termination message and sending it to logs when the same is
already done by the parallel worker.
---
.../replication/logical/applyparallelworker.c | 11 +---------
src/backend/replication/logical/launcher.c | 21 ++++++++++++++++---
src/include/replication/worker_internal.h | 2 +-
3 files changed, 20 insertions(+), 14 deletions(-)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index ee7a18137f..c79765ce20 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -577,16 +577,7 @@ pa_free_worker(ParallelApplyWorkerInfo *winfo)
list_length(ParallelApplyWorkerPool) >
(max_parallel_apply_workers_per_subscription / 2))
{
- int slot_no;
- uint16 generation;
-
- SpinLockAcquire(&winfo->shared->mutex);
- generation = winfo->shared->logicalrep_worker_generation;
- slot_no = winfo->shared->logicalrep_worker_slot_no;
- SpinLockRelease(&winfo->shared->mutex);
-
- logicalrep_pa_worker_stop(slot_no, generation);
-
+ logicalrep_pa_worker_stop(winfo);
pa_free_worker_info(winfo);
return;
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index ceea126231..ae107a2184 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -609,19 +609,34 @@ logicalrep_worker_stop(Oid subid, Oid relid)
}
/*
- * Stop the logical replication parallel apply worker corresponding to the
- * input slot number.
+ * Stop the given logical replication parallel apply worker.
*
* Node that the function sends SIGINT instead of SIGTERM to the parallel apply
* worker so that the worker exits cleanly.
*/
void
-logicalrep_pa_worker_stop(int slot_no, uint16 generation)
+logicalrep_pa_worker_stop(ParallelApplyWorkerInfo *winfo)
{
+ int slot_no;
+ uint16 generation;
LogicalRepWorker *worker;
+ SpinLockAcquire(&winfo->shared->mutex);
+ generation = winfo->shared->logicalrep_worker_generation;
+ slot_no = winfo->shared->logicalrep_worker_slot_no;
+ SpinLockRelease(&winfo->shared->mutex);
+
Assert(slot_no >= 0 && slot_no < max_logical_replication_workers);
+ /*
+ * Detach from the error_mq_handle for the parallel apply worker before
+ * terminating it. This prevents the leader apply worker from receiving the
+ * worker termination message and sending it to logs when the same is
+ * already done by the parallel worker.
+ */
+ shm_mq_detach(winfo->error_mq_handle);
+ winfo->error_mq_handle = NULL;
+
LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
worker = &LogicalRepCtx->workers[slot_no];
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index b57eed052f..343e781896 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -235,7 +235,7 @@ extern bool logicalrep_worker_launch(Oid dbid, Oid subid, const char *subname,
Oid userid, Oid relid,
dsm_handle subworker_dsm);
extern void logicalrep_worker_stop(Oid subid, Oid relid);
-extern void logicalrep_pa_worker_stop(int slot_no, uint16 generation);
+extern void logicalrep_pa_worker_stop(ParallelApplyWorkerInfo *winfo);
extern void logicalrep_worker_wakeup(Oid subid, Oid relid);
extern void logicalrep_worker_wakeup_ptr(LogicalRepWorker *worker);
--
2.30.0.windows.2
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:35 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-05-02 04:16 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-03 07:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-05 03:44 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
@ 2023-05-08 11:09 ` Amit Kapila <[email protected]>
2023-05-09 02:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
0 siblings, 1 reply; 105+ messages in thread
From: Amit Kapila @ 2023-05-08 11:09 UTC (permalink / raw)
To: Zhijie Hou (Fujitsu) <[email protected]>; +Cc: Masahiko Sawada <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, May 5, 2023 at 9:14 AM Zhijie Hou (Fujitsu)
<[email protected]> wrote:
>
> On Wednesday, May 3, 2023 3:17 PM Amit Kapila <[email protected]> wrote:
> >
>
> Attach another patch to fix the problem that pa_shutdown will access invalid
> MyLogicalRepWorker. I personally want to avoid introducing new static variable,
> so I only reorder the callback registration in this version.
>
> When testing this, I notice a rare case that the leader is possible to receive
> the worker termination message after the leader stops the parallel worker. This
> is unnecessary and have a risk that the leader would try to access the detached
> memory queue. This is more likely to happen and sometimes cause the failure in
> regression tests after the registration reorder patch because the dsm is
> detached earlier after applying the patch.
>
I think it is only possible for the leader apply can worker to try to
receive the error message from an error queue after your 0002 patch.
Because another place already detached from the queue before stopping
the parallel apply workers. So, I combined both the patches and
changed a few comments and a commit message. Let me know what you
think of the attached.
--
With Regards,
Amit Kapila.
Attachments:
[application/octet-stream] v2-0001-Fix-invalid-memory-access-during-the-shutdown-of-.patch (5.9K, ../../CAA4eK1LkPBTgcBxKrKahFu47oSK6rDq-AAs0oy4QXH6A8UzEig@mail.gmail.com/2-v2-0001-Fix-invalid-memory-access-during-the-shutdown-of-.patch)
download | inline diff:
From 12bcb55f98cbd30de80d95378a7b0df4152ea31a Mon Sep 17 00:00:00 2001
From: Amit Kapila <[email protected]>
Date: Mon, 8 May 2023 16:21:21 +0530
Subject: [PATCH v2] Fix invalid memory access during the shutdown of the
parallel apply worker.
The callback function pa_shutdown() accesses MyLogicalRepWorker which may
not be initialized if there is an error during the initialization of the
parallel apply worker. The other problem is that by the time it is invoked
even after the initialization of the worker, the MyLogicalRepWorker will
be reset by another callback logicalrep_worker_onexit. So, it won't have
the required information.
To fix this, register the shutdown callback after we are attached to the
worker slot.
After this fix, we observed another issue which is that sometimes the
leader apply worker tries to receive the message from the error queue that
might already be detached by the parallel apply worker leading to an
error. To prevent such an error, we ensure that the leader apply worker
detaches from the parallel apply worker's error queue before stopping it.
Reported-by: Sawada Masahiko
Author: Hou Zhijie
Reviewed-by: Amit Kapila
Discussion: https://postgr.es/m/CAD21AoDo+yUwNq6nTrvE2h9bB2vZfcag=jxWc7QxuWCmkDAqcA@mail.gmail.com
---
.../replication/logical/applyparallelworker.c | 23 +++++++++----------
src/backend/replication/logical/launcher.c | 21 ++++++++++++++---
src/include/replication/worker_internal.h | 2 +-
3 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index ee7a18137f..096d9f4bee 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -577,16 +577,7 @@ pa_free_worker(ParallelApplyWorkerInfo *winfo)
list_length(ParallelApplyWorkerPool) >
(max_parallel_apply_workers_per_subscription / 2))
{
- int slot_no;
- uint16 generation;
-
- SpinLockAcquire(&winfo->shared->mutex);
- generation = winfo->shared->logicalrep_worker_generation;
- slot_no = winfo->shared->logicalrep_worker_slot_no;
- SpinLockRelease(&winfo->shared->mutex);
-
- logicalrep_pa_worker_stop(slot_no, generation);
-
+ logicalrep_pa_worker_stop(winfo);
pa_free_worker_info(winfo);
return;
@@ -845,6 +836,9 @@ LogicalParallelApplyLoop(shm_mq_handle *mqh)
* Make sure the leader apply worker tries to read from our error queue one more
* time. This guards against the case where we exit uncleanly without sending
* an ErrorResponse, for example because some code calls proc_exit directly.
+ *
+ * Also explicitly detach from dsm segment to invoke on_dsm_detach callbacks,
+ * if any. See ParallelWorkerShutdown for details.
*/
static void
pa_shutdown(int code, Datum arg)
@@ -901,8 +895,6 @@ ParallelApplyWorkerMain(Datum main_arg)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("bad magic number in dynamic shared memory segment")));
- before_shmem_exit(pa_shutdown, PointerGetDatum(seg));
-
/* Look up the shared information. */
shared = shm_toc_lookup(toc, PARALLEL_APPLY_KEY_SHARED, false);
MyParallelShared = shared;
@@ -921,6 +913,13 @@ ParallelApplyWorkerMain(Datum main_arg)
*/
logicalrep_worker_attach(worker_slot);
+ /*
+ * Register the shutdown callback after we are attached to the worker slot.
+ * This is to ensure that MyLogicalRepWorker remains valid when this
+ * callback is invoked.
+ */
+ before_shmem_exit(pa_shutdown, PointerGetDatum(seg));
+
SpinLockAcquire(&MyParallelShared->mutex);
MyParallelShared->logicalrep_worker_generation = MyLogicalRepWorker->generation;
MyParallelShared->logicalrep_worker_slot_no = worker_slot;
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index ceea126231..ec34a925f7 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -609,19 +609,34 @@ logicalrep_worker_stop(Oid subid, Oid relid)
}
/*
- * Stop the logical replication parallel apply worker corresponding to the
- * input slot number.
+ * Stop the given logical replication parallel apply worker.
*
* Node that the function sends SIGINT instead of SIGTERM to the parallel apply
* worker so that the worker exits cleanly.
*/
void
-logicalrep_pa_worker_stop(int slot_no, uint16 generation)
+logicalrep_pa_worker_stop(ParallelApplyWorkerInfo *winfo)
{
+ int slot_no;
+ uint16 generation;
LogicalRepWorker *worker;
+ SpinLockAcquire(&winfo->shared->mutex);
+ generation = winfo->shared->logicalrep_worker_generation;
+ slot_no = winfo->shared->logicalrep_worker_slot_no;
+ SpinLockRelease(&winfo->shared->mutex);
+
Assert(slot_no >= 0 && slot_no < max_logical_replication_workers);
+ /*
+ * Detach from the error_mq_handle for the parallel apply worker before
+ * stopping it. This prevents the leader apply worker from trying to
+ * receive the message from the error queue that might already be detached
+ * by the parallel apply worker.
+ */
+ shm_mq_detach(winfo->error_mq_handle);
+ winfo->error_mq_handle = NULL;
+
LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
worker = &LogicalRepCtx->workers[slot_no];
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index b57eed052f..343e781896 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -235,7 +235,7 @@ extern bool logicalrep_worker_launch(Oid dbid, Oid subid, const char *subname,
Oid userid, Oid relid,
dsm_handle subworker_dsm);
extern void logicalrep_worker_stop(Oid subid, Oid relid);
-extern void logicalrep_pa_worker_stop(int slot_no, uint16 generation);
+extern void logicalrep_pa_worker_stop(ParallelApplyWorkerInfo *winfo);
extern void logicalrep_worker_wakeup(Oid subid, Oid relid);
extern void logicalrep_worker_wakeup_ptr(LogicalRepWorker *worker);
--
2.39.1
^ permalink raw reply [nested|flat] 105+ messages in thread
* Re: Perform streaming logical transactions by background workers and parallel apply
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:35 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-05-02 04:16 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-03 07:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-05 03:44 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-05-08 11:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
@ 2023-05-09 02:19 ` Masahiko Sawada <[email protected]>
0 siblings, 0 replies; 105+ messages in thread
From: Masahiko Sawada @ 2023-05-09 02:19 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Zhijie Hou (Fujitsu) <[email protected]>; Alexander Lakhin <[email protected]>; PostgreSQL Hackers <[email protected]>
On Mon, May 8, 2023 at 8:09 PM Amit Kapila <[email protected]> wrote:
>
> On Fri, May 5, 2023 at 9:14 AM Zhijie Hou (Fujitsu)
> <[email protected]> wrote:
> >
> > On Wednesday, May 3, 2023 3:17 PM Amit Kapila <[email protected]> wrote:
> > >
> >
> > Attach another patch to fix the problem that pa_shutdown will access invalid
> > MyLogicalRepWorker. I personally want to avoid introducing new static variable,
> > so I only reorder the callback registration in this version.
> >
> > When testing this, I notice a rare case that the leader is possible to receive
> > the worker termination message after the leader stops the parallel worker. This
> > is unnecessary and have a risk that the leader would try to access the detached
> > memory queue. This is more likely to happen and sometimes cause the failure in
> > regression tests after the registration reorder patch because the dsm is
> > detached earlier after applying the patch.
> >
>
> I think it is only possible for the leader apply can worker to try to
> receive the error message from an error queue after your 0002 patch.
> Because another place already detached from the queue before stopping
> the parallel apply workers. So, I combined both the patches and
> changed a few comments and a commit message. Let me know what you
> think of the attached.
I have one comment on the detaching error queue part:
+ /*
+ * Detach from the error_mq_handle for the parallel apply worker before
+ * stopping it. This prevents the leader apply worker from trying to
+ * receive the message from the error queue that might already
be detached
+ * by the parallel apply worker.
+ */
+ shm_mq_detach(winfo->error_mq_handle);
+ winfo->error_mq_handle = NULL;
In pa_detach_all_error_mq(), we try to detach error queues of all
workers in the pool. I think we should check if the queue is already
detached (i.e. is NULL) there. Otherwise, we will end up a SEGV if an
error happens after detaching the error queue and before removing the
worker from the pool.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 105+ messages in thread
end of thread, other threads:[~2023-05-09 02:19 UTC | newest]
Thread overview: 105+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2021-07-14 02:25 [PATCH 1/4] Add pg_am_size(), pg_namespace_size() .. Justin Pryzby <[email protected]>
2023-01-09 08:51 Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-09 09:32 ` RE: Perform streaming logical transactions by background workers and parallel apply Shinoda, Noriyoshi (PN Japan FSIP) <[email protected]>
2023-01-09 10:15 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-10 04:55 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-10 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Dilip Kumar <[email protected]>
2023-01-12 04:23 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-12 05:04 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 10:51 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 11:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 02:25 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-13 03:36 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-13 04:28 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-13 05:02 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 05:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-13 10:13 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-14 11:47 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 04:54 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-16 06:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 21:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 02:21 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 03:32 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 03:37 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 03:48 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-17 06:46 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-17 09:14 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-17 14:37 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-18 04:35 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-18 04:48 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-13 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-18 06:39 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-19 10:14 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-19 10:22 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-20 06:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-23 03:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-23 05:58 ` Re: Perform streaming logical transactions by background workers and parallel apply Dilip Kumar <[email protected]>
2023-01-23 08:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-23 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 03:43 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 04:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 07:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-24 12:47 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 12:49 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-24 14:34 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-24 21:45 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 04:35 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-25 06:27 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-25 06:51 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-27 16:36 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-24 23:30 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-25 14:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-26 03:36 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-30 06:24 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-30 12:57 ` RE: Perform streaming logical transactions by background workers and parallel apply Hayato Kuroda (Fujitsu) <[email protected]>
2023-01-30 00:10 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-30 06:11 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-30 04:12 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-30 06:23 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-30 14:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-31 03:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-31 05:40 ` Re: Perform streaming logical transactions by background workers and parallel apply Peter Smith <[email protected]>
2023-01-13 02:52 ` Re: Perform streaming logical transactions by background workers and parallel apply shveta malik <[email protected]>
2023-01-12 12:34 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-01-10 05:46 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
2023-01-10 06:31 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-15 17:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
2023-01-16 06:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-16 16:33 ` Re: Perform streaming logical transactions by background workers and parallel apply Tomas Vondra <[email protected]>
2023-01-17 03:05 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-17 03:29 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-17 04:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-01-17 05:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-01-17 06:05 ` RE: Perform streaming logical transactions by background workers and parallel apply [email protected] <[email protected]>
2023-04-24 01:55 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-24 02:50 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
2023-04-24 03:10 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
2023-04-24 03:29 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 04:03 ` Re: Perform streaming logical transactions by background workers and parallel apply Kyotaro Horiguchi <[email protected]>
2023-04-24 05:24 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-24 06:42 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-26 09:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-26 10:41 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-04-26 11:21 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 02:51 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-04-28 05:00 ` Re: Perform streaming logical transactions by background workers and parallel apply Alexander Lakhin <[email protected]>
2023-04-28 06:18 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-04-28 09:01 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-01 03:52 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:21 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-08 03:07 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-08 03:52 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-05-08 05:38 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-08 06:33 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-09 02:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
2023-05-02 03:35 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-05-02 04:16 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-03 07:17 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-05 03:44 ` RE: Perform streaming logical transactions by background workers and parallel apply Zhijie Hou (Fujitsu) <[email protected]>
2023-05-08 11:09 ` Re: Perform streaming logical transactions by background workers and parallel apply Amit Kapila <[email protected]>
2023-05-09 02:19 ` Re: Perform streaming logical transactions by background workers and parallel apply Masahiko Sawada <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox