diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index bbd908af05..73ca4f7884 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -1974,21 +1974,6 @@ 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 (rbtxn_is_serialized(txn) && 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 */ @@ -2623,8 +2608,7 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn, sz += sizeof(SnapshotData) + sizeof(TransactionId) * snap->xcnt + - sizeof(TransactionId) * snap->subxcnt - ; + sizeof(TransactionId) * snap->subxcnt; /* make sure we have enough space */ ReorderBufferSerializeReserve(rb, sz); @@ -2697,6 +2681,17 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn, } pgstat_report_wait_end(); + /* + * Keep the transaction's final_lsn up to date with each change we send to + * disk, so that ReorderBufferRestoreCleanup works correctly. (We used to + * only do this on commit and abort records, but that doesn't work if a + * system crash leaves a transaction without its abort record). + * + * Make sure not to move it backwards. + */ + if (txn->final_lsn < change->lsn) + txn->final_lsn = change->lsn; + Assert(ondisk->change.action == change->action); } diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h index 4f6c65d6f4..626ecf4dc9 100644 --- a/src/include/replication/reorderbuffer.h +++ b/src/include/replication/reorderbuffer.h @@ -207,9 +207,10 @@ typedef struct ReorderBufferTXN * * prepared transaction commit * * plain abort record * * prepared transaction abort - * * error during decoding - * * for a crashed transaction, the LSN of the last change, regardless of - * what it was. + * + * This can also become set to earlier values than transaction end when + * a transaction is spilled to disk; specifically it's set to the LSN of + * the latest change written to disk so far. * ---- */ XLogRecPtr final_lsn;