mirror of
https://github.com/postgres/postgres.git
synced 2025-10-27 00:12:01 +03:00
Add support for prepared transactions to built-in logical replication.
To add support for streaming transactions at prepare time into the built-in logical replication, we need to do the following things: * Modify the output plugin (pgoutput) to implement the new two-phase API callbacks, by leveraging the extended replication protocol. * Modify the replication apply worker, to properly handle two-phase transactions by replaying them on prepare. * Add a new SUBSCRIPTION option "two_phase" to allow users to enable two-phase transactions. We enable the two_phase once the initial data sync is over. We however must explicitly disable replication of two-phase transactions during replication slot creation, even if the plugin supports it. We don't need to replicate the changes accumulated during this phase, and moreover, we don't have a replication connection open so we don't know where to send the data anyway. The streaming option is not allowed with this new two_phase option. This can be done as a separate patch. We don't allow to toggle two_phase option of a subscription because it can lead to an inconsistent replica. For the same reason, we don't allow to refresh the publication once the two_phase is enabled for a subscription unless copy_data option is false. Author: Peter Smith, Ajin Cherian and Amit Kapila based on previous work by Nikhil Sontakke and Stas Kelvich Reviewed-by: Amit Kapila, Sawada Masahiko, Vignesh C, Dilip Kumar, Takamichi Osumi, Greg Nancarrow Tested-By: Haiying Tang Discussion: https://postgr.es/m/02DA5F5E-CECE-4D9C-8B4B-418077E2C010@postgrespro.ru Discussion: https://postgr.es/m/CAA4eK1+opiV4aFTmWWUF9h_32=HfPOW9vZASHarT0UA5oBrtGw@mail.gmail.com
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#ifndef LOGICAL_PROTO_H
|
||||
#define LOGICAL_PROTO_H
|
||||
|
||||
#include "access/xact.h"
|
||||
#include "replication/reorderbuffer.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
@@ -26,12 +27,16 @@
|
||||
* connect time.
|
||||
*
|
||||
* LOGICALREP_PROTO_STREAM_VERSION_NUM is the minimum protocol version with
|
||||
* support for streaming large transactions.
|
||||
* support for streaming large transactions. Introduced in PG14.
|
||||
*
|
||||
* LOGICALREP_PROTO_TWOPHASE_VERSION_NUM is the minimum protocol version with
|
||||
* support for two-phase commit decoding (at prepare time). Introduced in PG15.
|
||||
*/
|
||||
#define LOGICALREP_PROTO_MIN_VERSION_NUM 1
|
||||
#define LOGICALREP_PROTO_VERSION_NUM 1
|
||||
#define LOGICALREP_PROTO_STREAM_VERSION_NUM 2
|
||||
#define LOGICALREP_PROTO_MAX_VERSION_NUM LOGICALREP_PROTO_STREAM_VERSION_NUM
|
||||
#define LOGICALREP_PROTO_TWOPHASE_VERSION_NUM 3
|
||||
#define LOGICALREP_PROTO_MAX_VERSION_NUM LOGICALREP_PROTO_TWOPHASE_VERSION_NUM
|
||||
|
||||
/*
|
||||
* Logical message types
|
||||
@@ -55,6 +60,10 @@ typedef enum LogicalRepMsgType
|
||||
LOGICAL_REP_MSG_RELATION = 'R',
|
||||
LOGICAL_REP_MSG_TYPE = 'Y',
|
||||
LOGICAL_REP_MSG_MESSAGE = 'M',
|
||||
LOGICAL_REP_MSG_BEGIN_PREPARE = 'b',
|
||||
LOGICAL_REP_MSG_PREPARE = 'P',
|
||||
LOGICAL_REP_MSG_COMMIT_PREPARED = 'K',
|
||||
LOGICAL_REP_MSG_ROLLBACK_PREPARED = 'r',
|
||||
LOGICAL_REP_MSG_STREAM_START = 'S',
|
||||
LOGICAL_REP_MSG_STREAM_END = 'E',
|
||||
LOGICAL_REP_MSG_STREAM_COMMIT = 'c',
|
||||
@@ -122,6 +131,48 @@ typedef struct LogicalRepCommitData
|
||||
TimestampTz committime;
|
||||
} LogicalRepCommitData;
|
||||
|
||||
/*
|
||||
* Prepared transaction protocol information for begin_prepare, and prepare.
|
||||
*/
|
||||
typedef struct LogicalRepPreparedTxnData
|
||||
{
|
||||
XLogRecPtr prepare_lsn;
|
||||
XLogRecPtr end_lsn;
|
||||
TimestampTz prepare_time;
|
||||
TransactionId xid;
|
||||
char gid[GIDSIZE];
|
||||
} LogicalRepPreparedTxnData;
|
||||
|
||||
/*
|
||||
* Prepared transaction protocol information for commit prepared.
|
||||
*/
|
||||
typedef struct LogicalRepCommitPreparedTxnData
|
||||
{
|
||||
XLogRecPtr commit_lsn;
|
||||
XLogRecPtr end_lsn;
|
||||
TimestampTz commit_time;
|
||||
TransactionId xid;
|
||||
char gid[GIDSIZE];
|
||||
} LogicalRepCommitPreparedTxnData;
|
||||
|
||||
/*
|
||||
* Rollback Prepared transaction protocol information. The prepare information
|
||||
* prepare_end_lsn and prepare_time are used to check if the downstream has
|
||||
* received this prepared transaction in which case it can apply the rollback,
|
||||
* otherwise, it can skip the rollback operation. The gid alone is not
|
||||
* sufficient because the downstream node can have a prepared transaction with
|
||||
* same identifier.
|
||||
*/
|
||||
typedef struct LogicalRepRollbackPreparedTxnData
|
||||
{
|
||||
XLogRecPtr prepare_end_lsn;
|
||||
XLogRecPtr rollback_end_lsn;
|
||||
TimestampTz prepare_time;
|
||||
TimestampTz rollback_time;
|
||||
TransactionId xid;
|
||||
char gid[GIDSIZE];
|
||||
} LogicalRepRollbackPreparedTxnData;
|
||||
|
||||
extern void logicalrep_write_begin(StringInfo out, ReorderBufferTXN *txn);
|
||||
extern void logicalrep_read_begin(StringInfo in,
|
||||
LogicalRepBeginData *begin_data);
|
||||
@@ -129,6 +180,24 @@ extern void logicalrep_write_commit(StringInfo out, ReorderBufferTXN *txn,
|
||||
XLogRecPtr commit_lsn);
|
||||
extern void logicalrep_read_commit(StringInfo in,
|
||||
LogicalRepCommitData *commit_data);
|
||||
extern void logicalrep_write_begin_prepare(StringInfo out, ReorderBufferTXN *txn);
|
||||
extern void logicalrep_read_begin_prepare(StringInfo in,
|
||||
LogicalRepPreparedTxnData *begin_data);
|
||||
extern void logicalrep_write_prepare(StringInfo out, ReorderBufferTXN *txn,
|
||||
XLogRecPtr prepare_lsn);
|
||||
extern void logicalrep_read_prepare(StringInfo in,
|
||||
LogicalRepPreparedTxnData *prepare_data);
|
||||
extern void logicalrep_write_commit_prepared(StringInfo out, ReorderBufferTXN *txn,
|
||||
XLogRecPtr commit_lsn);
|
||||
extern void logicalrep_read_commit_prepared(StringInfo in,
|
||||
LogicalRepCommitPreparedTxnData *prepare_data);
|
||||
extern void logicalrep_write_rollback_prepared(StringInfo out, ReorderBufferTXN *txn,
|
||||
XLogRecPtr prepare_end_lsn,
|
||||
TimestampTz prepare_time);
|
||||
extern void logicalrep_read_rollback_prepared(StringInfo in,
|
||||
LogicalRepRollbackPreparedTxnData *rollback_data);
|
||||
|
||||
|
||||
extern void logicalrep_write_origin(StringInfo out, const char *origin,
|
||||
XLogRecPtr origin_lsn);
|
||||
extern char *logicalrep_read_origin(StringInfo in, XLogRecPtr *origin_lsn);
|
||||
|
||||
Reference in New Issue
Block a user