logical_decoding_xact_bookkeep.patch
application/octet-stream
Filename: logical_decoding_xact_bookkeep.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/replication/logical/decode.c | 49 | 1 |
| src/backend/replication/logical/reorderbuffer.c | 1 | 1 |
| src/backend/replication/logical/snapbuild.c | 9 | 5 |
| src/include/replication/reorderbuffer.h | 2 | 0 |
| src/include/replication/snapbuild.h | 1 | 1 |
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index 5f59613..2512912 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -42,6 +42,7 @@
#include "replication/reorderbuffer.h"
#include "replication/snapbuild.h"
#include "storage/standby.h"
+#include "utils/builtins.h"
typedef struct XLogRecordBuffer
{
@@ -85,6 +86,9 @@ static bool DecodeTXNNeedSkip(LogicalDecodingContext *ctx,
XLogRecordBuffer *buf, Oid dbId,
RepOriginId origin_id);
+/* record previous restart_lsn running xacts */
+xl_running_xacts *last_running = NULL;
+
/*
* Take every XLogReadRecord()ed record and perform the actions required to
* decode it using the output plugin already setup in the logical decoding
@@ -402,6 +406,28 @@ DecodeStandbyOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
{
xl_running_xacts *running = (xl_running_xacts *) XLogRecGetData(r);
+ /* record restart_lsn running xacts */
+ if (MyReplicationSlot && (buf->origptr == MyReplicationSlot->data.restart_lsn))
+ {
+ if (last_running)
+ free(last_running);
+
+ last_running = NULL;
+
+ /*
+ * xl_running_xacts contains a xids Flexible Array
+ * and its size is subxcnt + xcnt.
+ * Take that into account while allocating
+ * the memory for last_running.
+ */
+ last_running = (xl_running_xacts *) malloc(sizeof(xl_running_xacts)
+ + sizeof(TransactionId )
+ * (running->subxcnt + running->xcnt));
+ memcpy(last_running, running, sizeof(xl_running_xacts)
+ + (sizeof(TransactionId)
+ * (running->subxcnt + running->xcnt)));
+ }
+
SnapBuildProcessRunningXacts(builder, buf->origptr, running);
/*
@@ -678,6 +704,7 @@ DecodeCommit(LogicalDecodingContext *ctx, XLogRecordBuffer *buf,
TimestampTz commit_time = parsed->xact_time;
RepOriginId origin_id = XLogRecGetOrigin(buf->record);
int i;
+ bool force_travel_and_snapshot = false;
if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
{
@@ -685,8 +712,29 @@ DecodeCommit(LogicalDecodingContext *ctx, XLogRecordBuffer *buf,
commit_time = parsed->origin_timestamp;
}
+ /*
+ * Check if the commit contain catalog invalidations
+ * and if the xid was part of the restart_lsn
+ * running ones
+ */
+ if ((parsed->xinfo & XACT_XINFO_HAS_INVALS) && last_running)
+ {
+ /* make last_running->xids bsearch()able */
+ qsort(last_running->xids,
+ last_running->subxcnt + last_running->xcnt,
+ sizeof(TransactionId), xidComparator);
+
+ /*
+ * Is this xid part of the known running ones
+ * in the restart_lsn RUNNING_XACT entry?
+ */
+ force_travel_and_snapshot = TransactionIdInArray(xid, last_running->xids,
+ last_running->subxcnt
+ + last_running->xcnt);
+ }
+
SnapBuildCommitTxn(ctx->snapshot_builder, buf->origptr, xid,
- parsed->nsubxacts, parsed->subxacts);
+ parsed->nsubxacts, parsed->subxacts, force_travel_and_snapshot);
/* ----
* Check whether we are interested in this specific transaction, and tell
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 91600ac..4a5610b 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -4892,7 +4892,7 @@ ApplyLogicalMappingFile(HTAB *tuplecid_data, Oid relid, const char *fname)
/*
* Check whether the TransactionId 'xid' is in the pre-sorted array 'xip'.
*/
-static bool
+bool
TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num)
{
return bsearch(&xid, xip, num,
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index ed3acad..6be39d1 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -910,15 +910,19 @@ SnapBuildPurgeCommittedTxn(SnapBuild *builder)
*/
void
SnapBuildCommitTxn(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid,
- int nsubxacts, TransactionId *subxacts)
+ int nsubxacts, TransactionId *subxacts, bool force_travel_and_snapshot)
{
int nxact;
-
- bool needs_snapshot = false;
- bool needs_timetravel = false;
- bool sub_needs_timetravel = false;
+ bool needs_snapshot;
+ bool needs_timetravel;
+ bool sub_needs_timetravel;
TransactionId xmax = xid;
+ /*
+ * if force_travel_and_snapshot is set to true
+ * then proceed as if there are any catalog modifying subxacts.
+ */
+ needs_snapshot = needs_timetravel = sub_needs_timetravel = force_travel_and_snapshot;
/*
* Transactions preceding BUILDING_SNAPSHOT will neither be decoded, nor
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index 565a961..7fc79f3 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -685,4 +685,6 @@ void ReorderBufferSetRestartPoint(ReorderBuffer *, XLogRecPtr ptr);
void StartupReorderBuffer(void);
+extern bool TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num);
+
#endif
diff --git a/src/include/replication/snapbuild.h b/src/include/replication/snapbuild.h
index fbabce6..46f7df0 100644
--- a/src/include/replication/snapbuild.h
+++ b/src/include/replication/snapbuild.h
@@ -80,7 +80,7 @@ extern XLogRecPtr SnapBuildInitialConsistentPoint(SnapBuild *builder);
extern void SnapBuildCommitTxn(SnapBuild *builder, XLogRecPtr lsn,
TransactionId xid, int nsubxacts,
- TransactionId *subxacts);
+ TransactionId *subxacts, bool force_travel_and_snapshot);
extern bool SnapBuildProcessChange(SnapBuild *builder, TransactionId xid,
XLogRecPtr lsn);
extern void SnapBuildProcessNewCid(SnapBuild *builder, TransactionId xid,