Re: [HACKERS] logical decoding of two-phase transactions
Amit Kapila <amit.kapila16@gmail.com>
On Fri, Feb 26, 2021 at 9:56 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
>
> On Thu, Feb 25, 2021 at 12:32 PM Peter Smith <smithpb2250@gmail.com> wrote:
> >
>
> 5. You need to write/sync the spool file at prepare time because after
> restart between prepare and commit prepared the changes can be lost
> and won't be resent by the publisher assuming there are commits of
> other transactions between prepare and commit prepared. For the same
> reason, I am not sure if we can just rely on the in-memory hash table
> for it (prepare_spoolfile_exists). Sure, if it exists and there is no
> restart then it would be cheap to check in the hash table but I don't
> think it is guaranteed.
>
As we can't rely on the hash table, I think we can get rid of it and
always check if the corresponding file exists.
Few more comments on v43-0007-Fix-apply-worker-empty-prepare
====================================================
1.
+ * So the "table_states_not_ready" list might end up having a READY
+ * state it it even though
The above sentence doesn't sound correct to me.
2.
@@ -759,6 +798,79 @@ apply_handle_begin_prepare(StringInfo s)
{
..
+ */
+ if (!am_tablesync_worker())
+ {
I think here we should have an Assert for tablesync worker because it
should never receive prepare.
3.
+ while (BusyTablesyncs())
+ {
+ elog(DEBUG1, "apply_handle_begin_prepare - waiting for all sync
workers to be DONE/READY");
+
+ process_syncing_tables(begin_data.end_lsn);
..
+ if (begin_data.end_lsn < BiggestTablesyncLSN()
In both the above places, you need to use begin_data.final_lsn because
the prepare is yet not replayed so we can't use its end_lsn for
syncup.
4.
+/*
+ * Are there any tablesyncs which have still not yet reached
SYNCDONE/READY state?
+ */
+bool
+BusyTablesyncs()
The function name is not clear enough. Can we change it to something
like AnyTableSyncInProgress?
5.
+/*
+ * Are there any tablesyncs which have still not yet reached
SYNCDONE/READY state?
+ */
+bool
+BusyTablesyncs()
{
..
+ /*
+ * XXX - When the process_syncing_tables_for_sync changes the state
+ * from SYNCDONE to READY, that change is actually written directly
In the above comment, do you mean to process_syncing_tables_for_apply
because that is where we change state to READY? And, I don't think we
need to mark this comment as XXX.
6.
+ * XXX - Is there a potential timing problem here - e.g. if signal arrives
+ * while executing this then maybe we will set table_states_valid without
+ * refetching them?
+ */
+static void
+FetchTableStates(bool *started_tx)
..
Can you explain which race condition you are worried about here which
is not possible earlier but can happen after this patch?
7.
@@ -941,6 +1162,26 @@ apply_handle_stream_prepare(StringInfo s)
elog(DEBUG1, "received prepare for streamed transaction %u", xid);
/*
+ * Wait for all the sync workers to reach the SYNCDONE/READY state.
+ *
+ * This is same waiting logic as in appy_handle_begin_prepare function
+ * (see that function for more details about this).
+ */
+ if (!am_tablesync_worker())
+ {
+ while (BusyTablesyncs())
+ {
+ process_syncing_tables(prepare_data.end_lsn);
+
+ /* This latch is to prevent 100% CPU looping. */
+ (void) WaitLatch(MyLatch,
+ WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
+ 1000L, WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE);
+ ResetLatch(MyLatch);
+ }
+ }
I think we need similar handling in stream_prepare as in begin_prepare
for writing to spool file because this has the same danger. But here
we need to write it xid spool file in StreamXidHash. Another thing we
need to ensure is to sync that file in stream prepare so that it can
survive restarts. Then in apply_handle_commit_prepared, after checking
for prepared spool file, we need to check the existence of xid spool
file, and if the same exists then apply messages from that file.
Again, like begin_prepare, in apply_handle_stream_prepare also we
should have an Assert for table sync worker.
I feel that 2PC and streaming case is a bit complicated to deal with.
How about, for now, we won't allow users to enable streaming if 2PC
option is enabled for Subscription. This requires some change (error
out if both streaming and 2PC options are enabled) in both
createsubscrition and altersubscription but that change should be
fairly small. If we follow this, then in apply_dispatch (for case
LOGICAL_REP_MSG_STREAM_PREPARE), we should report an ERROR "invalid
logical replication message type".
--
With Regards,
Amit Kapila.
Commits
-
Add prepare API support for streaming transactions in logical replication.
- 63cf61cdeb7b 15.0 landed
-
Doc: minor improvements for logical replication protocol documentation.
- a5cb4f9829fb 15.0 cited
-
Fix test failure in 021_twophase.pl.
- eaf5321c3524 15.0 landed
-
Refactor to make common functions in proto.c and worker.c.
- 91f9861242cd 15.0 landed
-
Unify PostgresNode's new() and get_new_node() methods
- 201a76183e20 15.0 cited
-
Fix potential buffer overruns in proto.c.
- 01c3adcdd85f 15.0 landed
-
Add support for prepared transactions to built-in logical replication.
- a8fd13cab0ba 15.0 cited
-
Refactor function parse_subscription_options.
- 8aafb0261675 15.0 cited
-
Allow enabling two-phase option via replication protocol.
- cda03cfed6b8 15.0 cited
-
Don't use Asserts to check for violations of replication protocol.
- fe6a20ce54cb 14.0 cited
-
Improve psql tab completion for options of subcriptions and publications
- d08237b5b494 14.0 cited
-
Rearrange logrep worker's snapshot handling some more.
- 3a09d75b4f6c 14.0 cited
-
doc: Update information of new messages for logical replication.
- 15c1a9d9cb76 14.0 cited
-
ALTER SUBSCRIPTION ... ADD/DROP PUBLICATION
- 82ed7748b710 14.0 cited
-
Allow pgoutput to send logical decoding messages.
- ac4645c0157f 14.0 cited
-
Refactor function parse_output_parameters.
- 531737ddad21 14.0 cited
-
Avoid repeated decoding of prepared transactions after a restart.
- 8bdb1332eb51 14.0 cited
-
Fix an oversight in ReorderBufferFinishPrepared.
- ade89ba5f408 14.0 landed
-
Allow multiple xacts during table sync in logical replication.
- ce0fdbfe9722 14.0 cited
-
Fix replication of in-progress transactions in tablesync worker.
- 0926e96c4934 14.0 cited
-
Fix 'skip-empty-xacts' option in test_decoding for streaming mode.
- 9653f24ad830 14.0 cited
-
Use Enum for top level logical replication message types.
- 644f0d7cc9c2 14.0 cited
-
Add support for streaming to built-in logical replication.
- 464824323e57 14.0 cited
-
Fix the logical streaming test.
- 82a0ba7707e0 14.0 cited
-
Implement streaming mode in ReorderBuffer.
- 7259736a6e5b 14.0 cited
-
Extend the logical decoding output plugin API with stream methods.
- 45fdc9738b36 14.0 cited
-
Store 2PC GID in commit/abort WAL recs for logical decoding
- 1eb6d6527aae 11.0 cited