Skip to content

Commit 70f087c

Browse files
author
Commitfest Bot
committed
[CF 5479] v24 - Enable logical decoding when wal_level = 'replica' without a server restart
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5479 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CAD21AoB+xpZ-+_=Zkj_RRcGk8gexkt3Sx3eLBBeWVpUqOHGvBg@mail.gmail.com Author(s): Masahiko Sawada
2 parents d4baa32 + eacce91 commit 70f087c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1674
-137
lines changed

doc/src/sgml/config.sgml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3034,6 +3034,17 @@ include_dir 'conf.d'
30343034
many <command>UPDATE</command> and <command>DELETE</command> statements are
30353035
executed.
30363036
</para>
3037+
<para>
3038+
It is important to note that when <varname>wal_level</varname> is set to
3039+
<literal>replica</literal>, the effective WAL level can automatically change
3040+
based on the presence of <link linkend="logicaldecoding-replication-slots">
3041+
logical replication slots</link>. The system automatically increases the
3042+
effective WAL level to <literal>logical</literal> when creating the first
3043+
logical replication slot, and decreases it back to <literal>replica</literal>
3044+
when dropping the last logical replication slot. The current effective WAL
3045+
level can be monitored through <xref linkend="guc-effective-wal-level"/>
3046+
parameter.
3047+
</para>
30373048
<para>
30383049
In releases prior to 9.6, this parameter also allowed the
30393050
values <literal>archive</literal> and <literal>hot_standby</literal>.
@@ -11817,6 +11828,38 @@ dynamic_library_path = '/usr/local/lib/postgresql:$libdir'
1181711828
</listitem>
1181811829
</varlistentry>
1181911830

11831+
<varlistentry id="guc-effective-wal-level" xreflabel="effective_wal_level">
11832+
<term><varname>effective_wal_level</varname> (<type>enum</type>)
11833+
<indexterm>
11834+
<primary><varname>effective_wal_level</varname> configuration parameter</primary>
11835+
</indexterm>
11836+
</term>
11837+
<listitem>
11838+
<para>
11839+
Reports the actual WAL logging level currently in effect in the
11840+
system. This parameter shares the same set of values as
11841+
<xref linkend="guc-wal-level"/>, but reflects the operational WAL
11842+
level rather than the configured setting. For descriptions of
11843+
possible values, refer to the <varname>wal_level</varname>
11844+
parameter documentation.
11845+
</para>
11846+
<para>
11847+
The effective WAL level can differ from the configured
11848+
<varname>wal_level</varname> in certain situations. For example,
11849+
when <varname>wal_level</varname> is set to <literal>replica</literal>
11850+
and the system has one or more logical replication slots,
11851+
<varname>effective_wal_level</varname> will show <literal>logical</literal>
11852+
to indicate that the system is maintaining WAL records at
11853+
<literal>logical</literal> level equivalent.
11854+
</para>
11855+
<para>
11856+
On standby servers, <varname>effective_wal_level</varname> matches
11857+
the value of <varname>effective_wal_level</varname> from the most
11858+
upstream server in the replication chain.
11859+
</para>
11860+
</listitem>
11861+
</varlistentry>
11862+
1182011863
<varlistentry id="guc-huge-pages-status" xreflabel="huge_pages_status">
1182111864
<term><varname>huge_pages_status</varname> (<type>enum</type>)
1182211865
<indexterm>

doc/src/sgml/logical-replication.sgml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2377,7 +2377,7 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
23772377

23782378
<para>
23792379
<link linkend="guc-wal-level"><varname>wal_level</varname></link> must be
2380-
set to <literal>logical</literal>.
2380+
set to <literal>replica</literal> or <literal>logical</literal>.
23812381
</para>
23822382

23832383
<para>
@@ -2498,7 +2498,7 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
24982498
<para>
24992499
The new cluster must have
25002500
<link linkend="guc-wal-level"><varname>wal_level</varname></link> as
2501-
<literal>logical</literal>.
2501+
<literal>replica</literal> or <literal>logical</literal>.
25022502
</para>
25032503
</listitem>
25042504
<listitem>

doc/src/sgml/logicaldecoding.sgml

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747

4848
<para>
4949
Before you can use logical decoding, you must set
50-
<xref linkend="guc-wal-level"/> to <literal>logical</literal> and
50+
<xref linkend="guc-wal-level"/> to <literal>replica</literal> or higher and
5151
<xref linkend="guc-max-replication-slots"/> to at least 1. Then, you
5252
should connect to the target database (in the example
5353
below, <literal>postgres</literal>) as a superuser.
@@ -257,6 +257,47 @@ postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NU
257257
log</link>, which describe changes on a storage level, into an
258258
application-specific form such as a stream of tuples or SQL statements.
259259
</para>
260+
261+
<para>
262+
Logical decoding becomes available in two conditions:
263+
</para>
264+
<itemizedlist>
265+
<listitem>
266+
<para>
267+
When <xref linkend="guc-wal-level"/> is set to <literal>logical</literal>.
268+
</para>
269+
</listitem>
270+
<listitem>
271+
<para>
272+
When <xref linkend="guc-wal-level"/> is set to <literal>replica</literal>
273+
and at least one valid logical replication slot exists on the system.
274+
</para>
275+
</listitem>
276+
</itemizedlist>
277+
<para>
278+
If either condition is met, the operational WAL level becomes equivalent
279+
to <literal>logical</literal>, which can be monitored through the
280+
<xref linkend="guc-effective-wal-level"/> parameter.
281+
</para>
282+
<para>
283+
When <varname>wal_level</varname> is set to <literal>replica</literal>,
284+
logical decoding is automatically activated upon creation of the first
285+
logical replication slot. This activation process involves several steps
286+
and requires synchronization among processes, ensuring system-wide
287+
consistency. Conversely, if <varname>wal_level</varname> set to
288+
<literal>replica</literal> and the last logical replication slot is dropped
289+
or invalidated, logical decoding is automatically disabled. Note that the
290+
deactivation of logical decoding might take some time as it is performed
291+
asynchronously by the checkpointer process.
292+
</para>
293+
294+
<caution>
295+
<para>
296+
When <varname>wal_level</varname> is set to <literal>replica</literal>,
297+
dropping or invalidating the last logical slot disables logical decoding
298+
on the primary, resulting in slots on standbys being invalidated.
299+
</para>
300+
</caution>
260301
</sect2>
261302

262303
<sect2 id="logicaldecoding-replication-slots">
@@ -328,8 +369,7 @@ postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NU
328369
that could be needed by the logical decoding on the standby (as it does
329370
not know about the <literal>catalog_xmin</literal> on the standby).
330371
Existing logical slots on standby also get invalidated if
331-
<varname>wal_level</varname> on the primary is reduced to less than
332-
<literal>logical</literal>.
372+
logical decoding is disabled on the primary.
333373
This is done as soon as the standby detects such a change in the WAL stream.
334374
It means that, for walsenders that are lagging (if any), some WAL records up
335375
to the <varname>wal_level</varname> parameter change on the primary won't be

doc/src/sgml/ref/pg_createsubscriber.sgml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -379,12 +379,12 @@ PostgreSQL documentation
379379
<para>
380380
The source server must accept connections from the target server. The
381381
source server must not be in recovery. The source server must have <xref
382-
linkend="guc-wal-level"/> as <literal>logical</literal>. The source server
383-
must have <xref linkend="guc-max-replication-slots"/> configured to a value
384-
greater than or equal to the number of specified databases plus existing
385-
replication slots. The source server must have <xref
386-
linkend="guc-max-wal-senders"/> configured to a value greater than or equal
387-
to the number of specified databases and existing WAL sender processes.
382+
linkend="guc-wal-level"/> as <literal>replica</literal> or <literal>logical</literal>.
383+
The source server must have <xref linkend="guc-max-replication-slots"/>
384+
configured to a value greater than or equal to the number of specified
385+
databases plus existing replication slots. The source server must have
386+
<xref linkend="guc-max-wal-senders"/> configured to a value greater than or
387+
equal to the number of specified databases and existing WAL sender processes.
388388
</para>
389389
</refsect2>
390390

doc/src/sgml/system-views.sgml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3062,8 +3062,9 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
30623062
<listitem>
30633063
<para>
30643064
<literal>wal_level_insufficient</literal> means that the
3065-
primary doesn't have a <xref linkend="guc-wal-level"/> sufficient to
3066-
perform logical decoding. It is set only for logical slots.
3065+
logical decoding is disabled on the primary (See
3066+
<xref linkend="logicaldecoding-explanation-log-dec"/>). It is set
3067+
only for logical slots.
30673068
</para>
30683069
</listitem>
30693070
<listitem>

src/backend/access/heap/heapam.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8891,8 +8891,9 @@ log_heap_update(Relation reln, Buffer oldbuf,
88918891
*
88928892
* Skip this if we're taking a full-page image of the new page, as we
88938893
* don't include the new tuple in the WAL record in that case. Also
8894-
* disable if wal_level='logical', as logical decoding needs to be able to
8895-
* read the new tuple in whole from the WAL record alone.
8894+
* disable if logical decoding is enabled and the relation requires WAL to
8895+
* be logged for logical decoding, as it needs to be able to read the new
8896+
* tuple in whole from the WAL record alone.
88968897
*/
88978898
if (oldbuf == newbuf && !need_tuple_data &&
88988899
!XLogCheckBufferNeedsBackup(newbuf))
@@ -9064,8 +9065,8 @@ log_heap_update(Relation reln, Buffer oldbuf,
90649065
/*
90659066
* Perform XLogInsert of an XLOG_HEAP2_NEW_CID record
90669067
*
9067-
* This is only used in wal_level >= WAL_LEVEL_LOGICAL, and only for catalog
9068-
* tuples.
9068+
* This is only used when effective_wal_level is logical, and only for
9069+
* catalog tuples.
90699070
*/
90709071
static XLogRecPtr
90719072
log_heap_new_cid(Relation relation, HeapTuple tup)

src/backend/access/rmgrdesc/xlogdesc.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
6666
CheckPoint *checkpoint = (CheckPoint *) rec;
6767

6868
appendStringInfo(buf, "redo %X/%08X; "
69-
"tli %u; prev tli %u; fpw %s; wal_level %s; xid %u:%u; oid %u; multi %u; offset %u; "
69+
"tli %u; prev tli %u; fpw %s; wal_level %s; logical decoding %s; xid %u:%u; oid %u; multi %u; offset %u; "
7070
"oldest xid %u in DB %u; oldest multi %u in DB %u; "
7171
"oldest/newest commit timestamp xid: %u/%u; "
7272
"oldest running xid %u; %s",
@@ -75,6 +75,7 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
7575
checkpoint->PrevTimeLineID,
7676
checkpoint->fullPageWrites ? "true" : "false",
7777
get_wal_level_string(checkpoint->wal_level),
78+
checkpoint->logicalDecodingEnabled ? "true" : "false",
7879
EpochFromFullTransactionId(checkpoint->nextXid),
7980
XidFromFullTransactionId(checkpoint->nextXid),
8081
checkpoint->nextOid,
@@ -167,6 +168,13 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
167168
memcpy(&wal_level, rec, sizeof(int));
168169
appendStringInfo(buf, "wal_level %s", get_wal_level_string(wal_level));
169170
}
171+
else if (info == XLOG_LOGICAL_DECODING_STATUS_CHANGE)
172+
{
173+
bool enabled;
174+
175+
memcpy(&enabled, rec, sizeof(bool));
176+
appendStringInfoString(buf, enabled ? "true" : "false");
177+
}
170178
}
171179

172180
const char *
@@ -218,6 +226,9 @@ xlog_identify(uint8 info)
218226
case XLOG_CHECKPOINT_REDO:
219227
id = "CHECKPOINT_REDO";
220228
break;
229+
case XLOG_LOGICAL_DECODING_STATUS_CHANGE:
230+
id = "LOGICAL_DECODING_STATUS_CHANGE";
231+
break;
221232
}
222233

223234
return id;

src/backend/access/transam/xact.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -552,9 +552,9 @@ MarkCurrentTransactionIdLoggedIfAny(void)
552552
* operation in a subtransaction. We require that for logical decoding, see
553553
* LogicalDecodingProcessRecord.
554554
*
555-
* This returns true if wal_level >= logical and we are inside a valid
556-
* subtransaction, for which the assignment was not yet written to any WAL
557-
* record.
555+
* This returns true if effective_wal_level is logical and we are inside
556+
* a valid subtransaction, for which the assignment was not yet written to
557+
* any WAL record.
558558
*/
559559
bool
560560
IsSubxactTopXidLogPending(void)
@@ -563,7 +563,7 @@ IsSubxactTopXidLogPending(void)
563563
if (CurrentTransactionState->topXidLogged)
564564
return false;
565565

566-
/* wal_level has to be logical */
566+
/* effective_wal_level has to be logical */
567567
if (!XLogLogicalInfoActive())
568568
return false;
569569

@@ -682,14 +682,14 @@ AssignTransactionId(TransactionState s)
682682
}
683683

684684
/*
685-
* When wal_level=logical, guarantee that a subtransaction's xid can only
686-
* be seen in the WAL stream if its toplevel xid has been logged before.
687-
* If necessary we log an xact_assignment record with fewer than
688-
* PGPROC_MAX_CACHED_SUBXIDS. Note that it is fine if didLogXid isn't set
689-
* for a transaction even though it appears in a WAL record, we just might
690-
* superfluously log something. That can happen when an xid is included
691-
* somewhere inside a wal record, but not in XLogRecord->xl_xid, like in
692-
* xl_standby_locks.
685+
* When effective_wal_level is logical, guarantee that a subtransaction's
686+
* xid can only be seen in the WAL stream if its toplevel xid has been
687+
* logged before. If necessary we log an xact_assignment record with fewer
688+
* than PGPROC_MAX_CACHED_SUBXIDS. Note that it is fine if didLogXid isn't
689+
* set for a transaction even though it appears in a WAL record, we just
690+
* might superfluously log something. That can happen when an xid is
691+
* included somewhere inside a wal record, but not in XLogRecord->xl_xid,
692+
* like in xl_standby_locks.
693693
*/
694694
if (isSubXact && XLogLogicalInfoActive() &&
695695
!TopTransactionStateData.didLogXid)

0 commit comments

Comments
 (0)