aboutsummaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
authorAmit Kapila <akapila@postgresql.org>2021-01-04 08:34:50 +0530
committerAmit Kapila <akapila@postgresql.org>2021-01-04 08:34:50 +0530
commita271a1b50e9bec07e2ef3a05e38e7285113e4ce6 (patch)
treea3cd4b3e22169f548a6c92615f8e713f7001e30f /doc/src
parentca3b37487be333a1d241dab1bbdd17a211a88f43 (diff)
downloadpostgresql-a271a1b50e9bec07e2ef3a05e38e7285113e4ce6.tar.gz
postgresql-a271a1b50e9bec07e2ef3a05e38e7285113e4ce6.zip
Allow decoding at prepare time in ReorderBuffer.
This patch allows PREPARE-time decoding of two-phase transactions (if the output plugin supports this capability), in which case the transactions are replayed at PREPARE and then committed later when COMMIT PREPARED arrives. Now that we decode the changes before the commit, the concurrent aborts may cause failures when the output plugin consults catalogs (both system and user-defined). We detect such failures with a special sqlerrcode ERRCODE_TRANSACTION_ROLLBACK introduced by commit 7259736a6e and stop decoding the remaining changes. Then we rollback the changes when rollback prepared is encountered. Author: Ajin Cherian and Amit Kapila based on previous work by Nikhil Sontakke and Stas Kelvich Reviewed-by: Amit Kapila, Peter Smith, Sawada Masahiko, Arseny Sher, and Dilip Kumar Tested-by: Takamichi Osumi Discussion: https://postgr.es/m/02DA5F5E-CECE-4D9C-8B4B-418077E2C010@postgrespro.ru https://postgr.es/m/CAMGcDxeqEpWj3fTXwqhSwBdXd2RS9jzwWscO-XbeCfso6ts3+Q@mail.gmail.com
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/logicaldecoding.sgml104
1 files changed, 103 insertions, 1 deletions
diff --git a/doc/src/sgml/logicaldecoding.sgml b/doc/src/sgml/logicaldecoding.sgml
index d63f90ff282..cf705ed9cda 100644
--- a/doc/src/sgml/logicaldecoding.sgml
+++ b/doc/src/sgml/logicaldecoding.sgml
@@ -165,7 +165,58 @@ COMMIT 693
<keycombo action="simul"><keycap>Control</keycap><keycap>C</keycap></keycombo>
$ pg_recvlogical -d postgres --slot=test --drop-slot
</programlisting>
- </sect1>
+
+ <para>
+ The following example shows SQL interface that can be used to decode prepared
+ transactions. Before you use two-phase commit commands, you must set
+ <varname>max_prepared_transactions</varname> to at least 1. You must also set
+ the option 'two-phase-commit' to 1 while calling
+ <function>pg_logical_slot_get_changes</function>. Note that we will stream
+ the entire transaction after the commit if it is not already decoded.
+ </para>
+<programlisting>
+postgres=# BEGIN;
+postgres=*# INSERT INTO data(data) VALUES('5');
+postgres=*# PREPARE TRANSACTION 'test_prepared1';
+
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'two-phase-commit', '1');
+ lsn | xid | data
+-----------+-----+---------------------------------------------------------
+ 0/1689DC0 | 529 | BEGIN 529
+ 0/1689DC0 | 529 | table public.data: INSERT: id[integer]:3 data[text]:'5'
+ 0/1689FC0 | 529 | PREPARE TRANSACTION 'test_prepared1', txid 529
+(3 rows)
+
+postgres=# COMMIT PREPARED 'test_prepared1';
+postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'two-phase-commit', '1');
+ lsn | xid | data
+-----------+-----+--------------------------------------------
+ 0/1689DC0 | 529 | BEGIN 529
+ 0/1689DC0 | 529 | table public.data: INSERT: id[integer]:3 data[text]:'5'
+ 0/1689FC0 | 529 | PREPARE TRANSACTION 'test_prepared1', txid 529
+ 0/168A060 | 529 | COMMIT PREPARED 'test_prepared1', txid 529
+(4 row)
+
+postgres=#-- you can also rollback a prepared transaction
+postgres=# BEGIN;
+postgres=*# INSERT INTO data(data) VALUES('6');
+postgres=*# PREPARE TRANSACTION 'test_prepared2';
+postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'two-phase-commit', '1');
+ lsn | xid | data
+-----------+-----+---------------------------------------------------------
+ 0/168A180 | 530 | BEGIN 530
+ 0/168A1E8 | 530 | table public.data: INSERT: id[integer]:4 data[text]:'6'
+ 0/168A430 | 530 | PREPARE TRANSACTION 'test_prepared2', txid 530
+(3 rows)
+
+postgres=# ROLLBACK PREPARED 'test_prepared2';
+postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'two-phase-commit', '1');
+ lsn | xid | data
+-----------+-----+----------------------------------------------
+ 0/168A4B8 | 530 | ROLLBACK PREPARED 'test_prepared2', txid 530
+(1 row)
+</programlisting>
+</sect1>
<sect1 id="logicaldecoding-explanation">
<title>Logical Decoding Concepts</title>
@@ -1126,4 +1177,55 @@ stream_commit_cb(...); &lt;-- commit of the streamed transaction
</para>
</sect1>
+
+ <sect1 id="logicaldecoding-two-phase-commits">
+ <title>Two-phase commit support for Logical Decoding</title>
+
+ <para>
+ With the basic output plugin callbacks (eg., <function>begin_cb</function>,
+ <function>change_cb</function>, <function>commit_cb</function> and
+ <function>message_cb</function>) two-phase commit commands like
+ <command>PREPARE TRANSACTION</command>, <command>COMMIT PREPARED</command>
+ and <command>ROLLBACK PREPARED</command> are not decoded. While the
+ <command>PREPARE TRANSACTION</command> is ignored,
+ <command>COMMIT PREPARED</command> is decoded as a <command>COMMIT</command>
+ and <command>ROLLBACK PREPARED</command> is decoded as a
+ <command>ROLLBACK</command>.
+ </para>
+
+ <para>
+ To support the streaming of two-phase commands, an output plugin needs to
+ provide additional callbacks. There are multiple two-phase commit callbacks
+ that are required, (<function>begin_prepare_cb</function>,
+ <function>prepare_cb</function>, <function>commit_prepared_cb</function>,
+ <function>rollback_prepared_cb</function> and
+ <function>stream_prepare_cb</function>) and an optional callback
+ (<function>filter_prepare_cb</function>).
+ </para>
+
+ <para>
+ If the output plugin callbacks for decoding two-phase commit commands are
+ provided, then on <command>PREPARE TRANSACTION</command>, the changes of
+ that transaction are decoded, passed to the output plugin, and the
+ <function>prepare_cb</function> callback is invoked. This differs from the
+ basic decoding setup where changes are only passed to the output plugin
+ when a transaction is committed. The start of a prepared transaction is
+ indicated by the <function>begin_prepare_cb</function> callback.
+ </para>
+
+ <para>
+ When a prepared transaction is rollbacked using the
+ <command>ROLLBACK PREPARED</command>, then the
+ <function>rollback_prepared_cb</function> callback is invoked and when the
+ prepared transaction is committed using <command>COMMIT PREPARED</command>,
+ then the <function>commit_prepared_cb</function> callback is invoked.
+ </para>
+
+ <para>
+ Optionally the output plugin can specify a name pattern in the
+ <function>filter_prepare_cb</function> and transactions with gid containing
+ that name pattern will not be decoded as a two-phase commit transaction.
+ </para>
+
+ </sect1>
</chapter>