aboutsummaryrefslogtreecommitdiff
path: root/src/backend/replication/logical/reorderbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/replication/logical/reorderbuffer.c')
-rw-r--r--src/backend/replication/logical/reorderbuffer.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index ccbbcddc0b1..95f5c0adcb6 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -1689,8 +1689,8 @@ ReorderBufferAbortOld(ReorderBuffer *rb, TransactionId oldestRunningXid)
* Iterate through all (potential) toplevel TXNs and abort all that are
* older than what possibly can be running. Once we've found the first
* that is alive we stop, there might be some that acquired an xid earlier
- * but started writing later, but it's unlikely and they will cleaned up
- * in a later call to ReorderBufferAbortOld().
+ * but started writing later, but it's unlikely and they will be cleaned
+ * up in a later call to this function.
*/
dlist_foreach_modify(it, &rb->toplevel_by_lsn)
{
@@ -1700,6 +1700,21 @@ ReorderBufferAbortOld(ReorderBuffer *rb, TransactionId oldestRunningXid)
if (TransactionIdPrecedes(txn->xid, oldestRunningXid))
{
+ /*
+ * We set final_lsn on a transaction when we decode its commit or
+ * abort record, but we never see those records for crashed
+ * transactions. To ensure cleanup of these transactions, set
+ * final_lsn to that of their last change; this causes
+ * ReorderBufferRestoreCleanup to do the right thing.
+ */
+ if (txn->serialized && txn->final_lsn == 0)
+ {
+ ReorderBufferChange *last =
+ dlist_tail_element(ReorderBufferChange, node, &txn->changes);
+
+ txn->final_lsn = last->lsn;
+ }
+
elog(DEBUG2, "aborting old transaction %u", txn->xid);
/* remove potential on-disk data, and deallocate this tx */