aboutsummaryrefslogtreecommitdiff
path: root/src/backend/replication/logical/reorderbuffer.c
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2016-10-03 22:11:36 -0700
committerAndres Freund <andres@anarazel.de>2016-10-03 22:11:36 -0700
commit61633f79048d040aefeed68dcac0e0b996a06189 (patch)
tree8a7d0cd8a8b070088dbb13e2d9b181054439f02a /src/backend/replication/logical/reorderbuffer.c
parentd51924be886c2a05e691fa05b16cb6b30ab8370f (diff)
downloadpostgresql-61633f79048d040aefeed68dcac0e0b996a06189.tar.gz
postgresql-61633f79048d040aefeed68dcac0e0b996a06189.zip
Correct logical decoding restore behaviour for subtransactions.
Before initializing iteration over a subtransaction's changes, the last few changes were not spilled to disk. That's correct if the transaction didn't spill to disk, but otherwise... This bug can lead to missed or misorderd subtransaction contents when they were spilled to disk. Move spilling of the remaining in-memory changes to ReorderBufferIterTXNInit(), where it can easily be applied to the top transaction and, if present, subtransactions. Since this code had too many bugs already, noticeably increase test coverage. Fixes: #14319 Reported-By: Huan Ruan Discussion: <20160909012610.20024.58169@wrigleys.postgresql.org> Backport: 9,4-, where logical decoding was added
Diffstat (limited to 'src/backend/replication/logical/reorderbuffer.c')
-rw-r--r--src/backend/replication/logical/reorderbuffer.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index e2a502c4431..6ad7e7de76c 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -935,8 +935,12 @@ ReorderBufferIterTXNInit(ReorderBuffer *rb, ReorderBufferTXN *txn)
ReorderBufferChange *cur_change;
if (txn->nentries != txn->nentries_mem)
+ {
+ /* serialize remaining changes */
+ ReorderBufferSerializeTXN(rb, txn);
ReorderBufferRestoreChanges(rb, txn, &state->entries[off].fd,
&state->entries[off].segno);
+ }
cur_change = dlist_head_element(ReorderBufferChange, node,
&txn->changes);
@@ -960,10 +964,13 @@ ReorderBufferIterTXNInit(ReorderBuffer *rb, ReorderBufferTXN *txn)
ReorderBufferChange *cur_change;
if (cur_txn->nentries != cur_txn->nentries_mem)
+ {
+ /* serialize remaining changes */
+ ReorderBufferSerializeTXN(rb, cur_txn);
ReorderBufferRestoreChanges(rb, cur_txn,
&state->entries[off].fd,
&state->entries[off].segno);
-
+ }
cur_change = dlist_head_element(ReorderBufferChange, node,
&cur_txn->changes);
@@ -1367,10 +1374,6 @@ ReorderBufferCommit(ReorderBuffer *rb, TransactionId xid,
txn->origin_id = origin_id;
txn->origin_lsn = origin_lsn;
- /* serialize the last bunch of changes if we need start earlier anyway */
- if (txn->nentries_mem != txn->nentries)
- ReorderBufferSerializeTXN(rb, txn);
-
/*
* If this transaction didn't have any real changes in our database, it's
* OK not to have a snapshot. Note that ReorderBufferCommitChild will have