From d698bf83d16416cf7222c9e825004bdd6b12ad39 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Mon, 3 Nov 2008 19:24:03 +0000 Subject: [PATCH] Fix TransactionIdSetStatusBit so that it doesn't try to change a transaction from COMMITTED to SUBCOMMITTED during recovery. This wasn't previously possible, but it is now due to the recent changes on clog commit protocol for subtransactions. Simon Riggs --- src/backend/access/transam/clog.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index fcff3ea3cf..3d62417387 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -26,7 +26,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.48 2008/10/20 19:18:18 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.49 2008/11/03 19:24:03 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -321,13 +321,29 @@ TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, i int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT; char *byteptr; char byteval; + char curval; byteptr = ClogCtl->shared->page_buffer[slotno] + byteno; + curval = (*byteptr >> shift) & CLOG_XACT_BITMASK; - /* Current state should be 0, subcommitted or target state */ - Assert(((*byteptr >> bshift) & CLOG_XACT_BITMASK) == 0 || - ((*byteptr >> bshift) & CLOG_XACT_BITMASK) == TRANSACTION_STATUS_SUB_COMMITTED || - ((*byteptr >> bshift) & CLOG_XACT_BITMASK) == status); + /* + * When replaying transactions during recovery we still need to perform + * the two phases of subcommit and then commit. However, some transactions + * are already correctly marked, so we just treat those as a no-op which + * allows us to keep the following Assert as restrictive as possible. + */ + if (InRecovery && status == TRANSACTION_STATUS_SUB_COMMITTED && + curval == TRANSACTION_STATUS_COMMITTED) + return; + + /* + * Current state change should be from 0 or subcommitted to target state + * or we should already be there when replaying changes during recovery. + */ + Assert(curval == 0 || + (curval == TRANSACTION_STATUS_SUB_COMMITTED && + status != TRANSACTION_STATUS_IN_PROGRESS) || + curval == status); /* note this assumes exclusive access to the clog page */ byteval = *byteptr; -- 2.40.0