Skip to content

Commit 53b4a2c

Browse files
author
Commitfest Bot
committed
[CF 5479] v12 - 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/CAD21AoAz1RkCfs-VD6Sm9bCFKiDC=9O-KAtcjxXeL76O3z8PaQ@mail.gmail.com Author(s): Masahiko Sawada
2 parents 317c117 + b993959 commit 53b4a2c

Some content is hidden

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

45 files changed

+1401
-144
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>.
@@ -11747,6 +11758,38 @@ dynamic_library_path = '/usr/local/lib/postgresql:$libdir'
1174711758
</listitem>
1174811759
</varlistentry>
1174911760

11761+
<varlistentry id="guc-effective-wal-level" xreflabel="effective_wal_level">
11762+
<term><varname>effective_wal_level</varname> (<type>enum</type>)
11763+
<indexterm>
11764+
<primary><varname>effective_wal_level</varname> configuration parameter</primary>
11765+
</indexterm>
11766+
</term>
11767+
<listitem>
11768+
<para>
11769+
Reports the actual WAL logging level currently in effect in the
11770+
system. This parameter shares the same set of values as
11771+
<xref linkend="guc-wal-level"/>, but reflects the operational WAL
11772+
level rather than the configured setting. For descriptions of
11773+
possible values, refer to the <varname>wal_level</varname>
11774+
parameter documentation.
11775+
</para>
11776+
<para>
11777+
The effective WAL level can differ from the configured
11778+
<varname>wal_level</varname> in certain situations. For example,
11779+
when <varname>wal_level</varname> is set to <literal>replica</literal>
11780+
and the system has one or more logical replication slots,
11781+
<varname>effective_wal_level</varname> will show <literal>logical</literal>
11782+
to indicate that the system is maintaining WAL records at
11783+
<literal>logical</literal> level equivalent.
11784+
</para>
11785+
<para>
11786+
On standby servers, <varname>effective_wal_level</varname> matches
11787+
the value of <varname>effective_wal_level</varname> from the most
11788+
upstream server in the replication chain.
11789+
</para>
11790+
</listitem>
11791+
</varlistentry>
11792+
1175011793
<varlistentry id="guc-huge-pages-status" xreflabel="huge_pages_status">
1175111794
<term><varname>huge_pages_status</varname> (<type>enum</type>)
1175211795
<indexterm>

doc/src/sgml/logical-replication.sgml

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

23762376
<para>
23772377
<link linkend="guc-wal-level"><varname>wal_level</varname></link> must be
2378-
set to <literal>logical</literal>.
2378+
set to <literal>replica</literal> or <literal>logical</literal>.
23792379
</para>
23802380

23812381
<para>
@@ -2496,7 +2496,7 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
24962496
<para>
24972497
The new cluster must have
24982498
<link linkend="guc-wal-level"><varname>wal_level</varname></link> as
2499-
<literal>logical</literal>.
2499+
<literal>replica</literal> or <literal>logical</literal>.
25002500
</para>
25012501
</listitem>
25022502
<listitem>

doc/src/sgml/logicaldecoding.sgml

Lines changed: 28 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,32 @@ 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 logical replication slot exists on the system.
274+
</para>
275+
</listitem>
276+
</itemizedlist>
277+
<para>
278+
When <varname>wal_level</varname> is set to <literal>replica</literal>,
279+
logical decoding is automatically activated upon creation of the first
280+
logical replication slot. This activation process involves several steps
281+
and requires waiting for any concurrent transactions to finish, ensuring
282+
system-wide consistency. Conversely, when the last logical replication slot
283+
is dropped from a system with <varname>wal_level</varname> set to
284+
<literal>replica</literal>, logical decoding is automatically disabled.
285+
</para>
260286
</sect2>
261287

262288
<sect2 id="logicaldecoding-replication-slots">
@@ -328,8 +354,7 @@ postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NU
328354
that could be needed by the logical decoding on the standby (as it does
329355
not know about the <literal>catalog_xmin</literal> on the standby).
330356
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>.
357+
logical decoding becomes disabled on the primary.
333358
This is done as soon as the standby detects such a change in the WAL stream.
334359
It means that, for walsenders that are lagging (if any), some WAL records up
335360
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
@@ -2996,8 +2996,9 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
29962996
<listitem>
29972997
<para>
29982998
<literal>wal_level_insufficient</literal> means that the
2999-
primary doesn't have a <xref linkend="guc-wal-level"/> sufficient to
3000-
perform logical decoding. It is set only for logical slots.
2999+
logical decoding is disabled on primary due to insufficient
3000+
<xref linkend="guc-wal-level"/> or no logical slots. It is set only
3001+
for logical slots.
30013002
</para>
30023003
</listitem>
30033004
<listitem>

src/backend/access/heap/heapam.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8884,8 +8884,8 @@ log_heap_update(Relation reln, Buffer oldbuf,
88848884
*
88858885
* Skip this if we're taking a full-page image of the new page, as we
88868886
* don't include the new tuple in the WAL record in that case. Also
8887-
* disable if wal_level='logical', as logical decoding needs to be able to
8888-
* read the new tuple in whole from the WAL record alone.
8887+
* disable if logical decoding is enabled, as logical decoding needs to be
8888+
* able to read the new tuple in whole from the WAL record alone.
88898889
*/
88908890
if (oldbuf == newbuf && !need_tuple_data &&
88918891
!XLogCheckBufferNeedsBackup(newbuf))
@@ -9057,8 +9057,8 @@ log_heap_update(Relation reln, Buffer oldbuf,
90579057
/*
90589058
* Perform XLogInsert of an XLOG_HEAP2_NEW_CID record
90599059
*
9060-
* This is only used in wal_level >= WAL_LEVEL_LOGICAL, and only for catalog
9061-
* tuples.
9060+
* This is only used when XLogLogicalInfoActive() is true, and only for
9061+
* catalog tuples.
90629062
*/
90639063
static XLogRecPtr
90649064
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
@@ -551,9 +551,9 @@ MarkCurrentTransactionIdLoggedIfAny(void)
551551
* operation in a subtransaction. We require that for logical decoding, see
552552
* LogicalDecodingProcessRecord.
553553
*
554-
* This returns true if wal_level >= logical and we are inside a valid
555-
* subtransaction, for which the assignment was not yet written to any WAL
556-
* record.
554+
* This returns true if XLogLogicalInfoActive() is true and we are inside
555+
* a valid subtransaction, for which the assignment was not yet written to
556+
* any WAL record.
557557
*/
558558
bool
559559
IsSubxactTopXidLogPending(void)
@@ -562,7 +562,7 @@ IsSubxactTopXidLogPending(void)
562562
if (CurrentTransactionState->topXidLogged)
563563
return false;
564564

565-
/* wal_level has to be logical */
565+
/* effective WAL level has to be logical */
566566
if (!XLogLogicalInfoActive())
567567
return false;
568568

@@ -681,14 +681,14 @@ AssignTransactionId(TransactionState s)
681681
}
682682

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

0 commit comments

Comments
 (0)