<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>12. Logical Replication on Hironobu SUZUKI @ InterDB</title>
    <link>http://www.interdb.jp/pg/pgsql12/index.html</link>
    <description>Recent content in 12. Logical Replication on Hironobu SUZUKI @ InterDB</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language><atom:link href="http://www.interdb.jp/pg/pgsql12/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>12.1. Overview</title>
      <link>http://www.interdb.jp/pg/pgsql12/01.html</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://www.interdb.jp/pg/pgsql12/01.html</guid>
      <description>&lt;h5&gt;&lt;font color=&#34;#0000ff&#34;&gt;Alpha Version: Work in progress.&lt;/font&gt;&lt;/h5&gt;
&lt;p&gt;This section introduces key concepts that are necessary to understand the descriptions in the subsequent sections.&lt;/p&gt;

&lt;div class=&#34;box notices cstyle default&#34;&gt;
  &lt;div class=&#34;box-label&#34;&gt;Section Contents&lt;/div&gt;
  &lt;div class=&#34;box-content&#34;&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;./01.html#1211-related-processes&#34;&gt;12.1.1. Related Processes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./01.html#1212-outline-of-logical-replication&#34;&gt;12.1.2. Outline of Logical Replication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./01.html#1213-replica-identity&#34;&gt;12.1.3. Replica Identity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./01.html#1214-replication-origin&#34;&gt;12.1.4. Replication Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./01.html#1215-replication-slot&#34;&gt;12.1.5. Replication Slot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./01.html#1216-conflicts&#34;&gt;12.1.6. Conflicts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;1211-related-processes&#34;&gt;12.1.1. Related Processes&lt;/h2&gt;
&lt;p&gt;In logical replication, four types of processes work cooperatively:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;walsender&lt;/strong&gt; on the Publisher mainly sends WAL data to the Subscriber, and does some various jobs.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;logical replication launcher&lt;/strong&gt; on the Subscriber launches apply workers.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;apply worker&lt;/strong&gt; on the Subscriber establishes a connection with the publisher&amp;rsquo;s walsender, receives the stream of logical changes, parses these messages, and updates the target tables accordingly.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;table sync worker&lt;/strong&gt; on the Subscriber performs the initial data synchronization for a specific table, catching up to the main replication stream before handing over further updates to the apply worker. Refer to &lt;a href=&#34;./02.html#1222-creating-subscription&#34;&gt;Section 12.2.2&lt;/a&gt; for details.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;1212-outline-of-logical-replication&#34;&gt;12.1.2. Outline of Logical Replication&lt;/h2&gt;
&lt;p&gt;PostgreSQL&amp;rsquo;s logical replication is inherently &lt;strong&gt;row-based&lt;/strong&gt;.
It captures changes to individual rows and streams them in a decoded format, ensuring consistency even when using non-deterministic functions, while remaining independent of the physical storage layout.&lt;/p&gt;</description>
    </item>
    <item>
      <title>12.2. Starting Logical Replication</title>
      <link>http://www.interdb.jp/pg/pgsql12/02.html</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://www.interdb.jp/pg/pgsql12/02.html</guid>
      <description>&lt;h5&gt;&lt;font color=&#34;#0000ff&#34;&gt;Alpha Version: Work in progress.&lt;/font&gt;&lt;/h5&gt;
&lt;p&gt;Before setting up logical replication, we assume the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Publisher has the tables that will be replicated to the Subscriber.&lt;/li&gt;
&lt;li&gt;The Subscriber has already created tables with the same structure as those on the Publisher, but without any data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this section, we use the following tables:&lt;/p&gt;
&lt;div class=&#34;wrap-code highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt; tbl_1 (id int &lt;span style=&#34;color:#66d9ef&#34;&gt;PRIMARY&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;KEY&lt;/span&gt;, name text, &lt;span style=&#34;color:#66d9ef&#34;&gt;data&lt;/span&gt; int);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt; tbl_2 (id int &lt;span style=&#34;color:#66d9ef&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NULL&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;UNIQUE&lt;/span&gt;, name text, &lt;span style=&#34;color:#66d9ef&#34;&gt;data&lt;/span&gt; int);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;INDEX&lt;/span&gt; tbl_2_idx &lt;span style=&#34;color:#66d9ef&#34;&gt;on&lt;/span&gt; tbl_2 (id, name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt; tbl_3 (id int, name text, &lt;span style=&#34;color:#66d9ef&#34;&gt;data&lt;/span&gt; int);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ALTER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt; tbl_3 REPLICA &lt;span style=&#34;color:#66d9ef&#34;&gt;IDENTITY&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FULL&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To set up logical replication, two commands are issued:&lt;/p&gt;</description>
    </item>
    <item>
      <title>12.3. ReorderBuffer Structure</title>
      <link>http://www.interdb.jp/pg/pgsql12/03.html</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://www.interdb.jp/pg/pgsql12/03.html</guid>
      <description>&lt;h5&gt;&lt;font color=&#34;#0000ff&#34;&gt;Alpha Version: Work in progress.&lt;/font&gt;&lt;/h5&gt;
&lt;p&gt;A &lt;strong&gt;ReorderBuffer&lt;/strong&gt; area is allocated for each walsender process.
The size of this area is limited by the &lt;a href=&#34;https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-LOGICAL-DECODING-WORK-MEM&#34; target=&#34;_blank&#34;&gt;logical_decoding_work_mem&lt;/a&gt;  configuration parameter (the default is 64MB).&lt;/p&gt;
&lt;p&gt;The ReorderBuffer consists of the following three components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/postgres/postgres/blob/REL_18_STABLE/src/include/replication/reorderbuffer.h#L574&#34; target=&#34;_blank&#34;&gt;ReorderBuffer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/postgres/postgres/blob/REL_18_STABLE/src/include/replication/reorderbuffer.h#L293&#34; target=&#34;_blank&#34;&gt;ReorderBufferTXN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/postgres/postgres/blob/REL_18_STABLE/src/include/replication/reorderbuffer.h#L76&#34; target=&#34;_blank&#34;&gt;ReorderBufferChange&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&#34;center&#34;&gt;
    &lt;img src=&#34;./fig-12-11.png&#34; width=&#34;720px&#34;/&gt; &lt;figcaption&gt;
            &lt;h6&gt;Figure 12.11. ReorderBuffer Structure.&lt;/h6&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;


&lt;p&gt;The central element of the &lt;strong&gt;ReorderBuffer&lt;/strong&gt; structure is the &lt;em&gt;by_txn&lt;/em&gt; hash table, which uses the transaction ID (txid) as its key.
Each entry in this hash table is a &lt;strong&gt;ReorderBufferTXN&lt;/strong&gt; structure, which stores metadata and the actual WAL data associated with each transaction.&lt;/p&gt;</description>
    </item>
    <item>
      <title>12.4. WAL Data Filtering and Buffering</title>
      <link>http://www.interdb.jp/pg/pgsql12/04.html</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://www.interdb.jp/pg/pgsql12/04.html</guid>
      <description>&lt;h5&gt;&lt;font color=&#34;#0000ff&#34;&gt;Alpha Version: Work in progress.&lt;/font&gt;&lt;/h5&gt;
&lt;p&gt;This section describes the data filtering and buffering mechanism within the ReorderBuffer.&lt;/p&gt;
&lt;p&gt;The discussion begins with the multi-stage filtering process executed by the walsender, which determines which records are eligible for decoding.
This is followed by a practical demonstration of how the ReorderBuffer accumulates these changes through a concrete transaction scenario.&lt;/p&gt;
&lt;p&gt;Furthermore, it explains the differences in WAL data storage for UPDATE and DELETE statements based on the &lt;strong&gt;Replica Identity&lt;/strong&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>12.5. Logical Decoding Output Plugins: pgoutput</title>
      <link>http://www.interdb.jp/pg/pgsql12/05.html</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://www.interdb.jp/pg/pgsql12/05.html</guid>
      <description>&lt;h5&gt;&lt;font color=&#34;#0000ff&#34;&gt;Alpha Version: Work in progress.&lt;/font&gt;&lt;/h5&gt;
&lt;p&gt;The primary role of an output plugin is to serialize the change data—which has been organized and reordered by the &lt;strong&gt;ReorderBuffer&lt;/strong&gt; — into a format compatible with sending to a subscriber.&lt;/p&gt;
&lt;p&gt;The specific tasks performed by the plugin include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Data Transformation and Filtering:&lt;/strong&gt; The plugin performs a final validation of the binary data within the ReorderBuffer against the publication&amp;rsquo;s configuration. It determines whether the target table or specific actions (e.g., INSERT, TRUNCATE) are included in the subscription and evaluates row filters or column lists. Once irrelevant data is excluded, the plugin formats the remaining payload into the appropriate data types and structures (e.g., text or binary) dictated by the replication protocol.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Message Generation:&lt;/strong&gt; The plugin constructs a logical sequence of messages, such as BEGIN, INSERT/UPDATE/DELETE/TRUNCATE, and COMMIT. These messages are passed to the walsender process, which manages the network sending.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As the name implies, this mechanism is &lt;strong&gt;pluggable&lt;/strong&gt;.
Custom plugins can be implemented to support unique output formats or specialized internal processing logic.
In standard PostgreSQL logical replication, the officially supported &lt;strong&gt;pgoutput&lt;/strong&gt; is used as the default plugin.&lt;/p&gt;</description>
    </item>
    <item>
      <title>12.6. Transaction Reassembly and Sending Message</title>
      <link>http://www.interdb.jp/pg/pgsql12/06.html</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://www.interdb.jp/pg/pgsql12/06.html</guid>
      <description>&lt;h5&gt;&lt;font color=&#34;#0000ff&#34;&gt;Alpha Version: Work in progress.&lt;/font&gt;&lt;/h5&gt;
&lt;p&gt;This section describes how the ReorderBuffer reassembles accumulated changes and performs the sending process to the subscriber&amp;rsquo;s apply worker via an output plugin.&lt;/p&gt;

&lt;div class=&#34;box notices cstyle default&#34;&gt;
  &lt;div class=&#34;box-label&#34;&gt;Section Contents&lt;/div&gt;
  &lt;div class=&#34;box-content&#34;&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;./06.html#1261-outline-of-transaction-reassembly&#34;&gt;12.6.1. Outline of Transaction Reassembly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./06.html#1262-sending-messages&#34;&gt;12.6.2. Sending Messages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./06.html#1263-streaming-of-large-transactions&#34;&gt;12.6.3. Streaming of Large Transactions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 id=&#34;1261-outline-of-transaction-reassembly&#34;&gt;12.6.1. Outline of Transaction Reassembly&lt;/h4&gt;
&lt;p&gt;When the walsender detects a &lt;strong&gt;COMMIT&lt;/strong&gt; record in the WAL, the ReorderBuffer initiates the reassembly process.
It organizes the captured changes in LSN order and passes them to the output plugin.
After the plugin completes the processing of the transaction, the ReorderBuffer releases the associated memory by deleting the change records and the &lt;code&gt;ReorderBufferTXN&lt;/code&gt; entry.&lt;/p&gt;</description>
    </item>
    <item>
      <title>12.7. Apply Worker and Transaction Replay</title>
      <link>http://www.interdb.jp/pg/pgsql12/07.html</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://www.interdb.jp/pg/pgsql12/07.html</guid>
      <description>&lt;h5&gt;&lt;font color=&#34;#0000ff&#34;&gt;Alpha Version: Work in progress.&lt;/font&gt;&lt;/h5&gt;
&lt;p&gt;The apply worker is the core component responsible for replaying logical changes received from the publisher onto the subscriber&amp;rsquo;s local tables.&lt;/p&gt;
&lt;p&gt;This section first reviews the fundamental operation of the apply worker, followed by an analysis of advanced modes involving the incremental processing of large transactions and the coordinated use of parallel apply workers.&lt;/p&gt;

&lt;div class=&#34;box notices cstyle default&#34;&gt;
  &lt;div class=&#34;box-label&#34;&gt;Section Contents&lt;/div&gt;
  &lt;div class=&#34;box-content&#34;&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;./07.html#1271-process-overview-streaming--off&#34;&gt;12.7.1. Process Overview (streaming = off)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./07.html#1272-streaming-mode-streaming--on&#34;&gt;12.7.2. Streaming Mode (streaming = on)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./07.html#1273-parallel-apply-worker-mode-streaming--parallel&#34;&gt;12.7.3. Parallel Apply Worker Mode (streaming = parallel)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;1271-process-overview-streaming--off&#34;&gt;12.7.1. Process Overview (streaming = off)&lt;/h2&gt;
&lt;p&gt;The apply worker on the subscriber node performs the following primary tasks:&lt;/p&gt;</description>
    </item>
    <item>
      <title>12.8. Internal Mechanism of Restart and Crash Recovery</title>
      <link>http://www.interdb.jp/pg/pgsql12/08.html</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://www.interdb.jp/pg/pgsql12/08.html</guid>
      <description>&lt;h5&gt;&lt;font color=&#34;#0000ff&#34;&gt;Alpha Version: Work in progress.&lt;/font&gt;&lt;/h5&gt;
&lt;p&gt;This section provides an overview of Write-Ahead Log (WAL) data management in logical replication.
Based on these fundamentals, it then details the sequences for subscriber restarts and crash recovery.&lt;/p&gt;

&lt;div class=&#34;box notices cstyle default&#34;&gt;
  &lt;div class=&#34;box-label&#34;&gt;Section Contents&lt;/div&gt;
  &lt;div class=&#34;box-content&#34;&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;./08.html#1281-wal-data-management&#34;&gt;12.8.1. WAL Data Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./08.html#1282-restart-sequence&#34;&gt;12.8.2. Restart Sequence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./08.html#1283-recovery-sequence&#34;&gt;12.8.3. Recovery Sequence&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;1281-wal-data-management&#34;&gt;12.8.1. WAL Data Management&lt;/h2&gt;
&lt;p&gt;Replication progress is managed based on the Log Sequence Number (LSN) of WAL data.&lt;/p&gt;
&lt;p&gt;Unlike streaming replication, where the primary and standby share the exact same WAL space, logical replication requires a &lt;strong&gt;mapping&lt;/strong&gt; between the publisher&amp;rsquo;s and subscriber&amp;rsquo;s WAL spaces, as each utilizes its own independent LSN.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>