diff options
author | Andres Freund <andres@anarazel.de> | 2016-10-03 22:11:36 -0700 |
---|---|---|
committer | Andres Freund <andres@anarazel.de> | 2016-10-03 22:13:10 -0700 |
commit | ce603a34a4568e876c0d9c826325d9b12c9e5497 (patch) | |
tree | cd1a9940aced8cb408cf8aa7ac752f6fbb807195 /src | |
parent | f50fa46cca9a1e5bfd517f7f1d979ef4db55ce03 (diff) | |
download | postgresql-ce603a34a4568e876c0d9c826325d9b12c9e5497.tar.gz postgresql-ce603a34a4568e876c0d9c826325d9b12c9e5497.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')
-rw-r--r-- | src/backend/replication/logical/reorderbuffer.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index 74b33c5ec4b..3e40a30efd7 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -874,8 +874,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); @@ -899,10 +903,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); @@ -1308,10 +1315,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 |