diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index fcc41ddb7c9e4..1208da29727ae 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -1670,8 +1670,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) { @@ -1681,6 +1681,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 */ diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h index f52a88dcd6457..0970abca52ae3 100644 --- a/src/include/replication/reorderbuffer.h +++ b/src/include/replication/reorderbuffer.h @@ -168,6 +168,8 @@ typedef struct ReorderBufferTXN * * plain abort record * * prepared transaction abort * * error during decoding + * * for a crashed transaction, the LSN of the last change, regardless of + * what it was. * ---- */ XLogRecPtr final_lsn;