Commit d698bf83 authored by Alvaro Herrera's avatar Alvaro Herrera

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
parent 13fc2e4d
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 ...@@ -321,13 +321,29 @@ TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, i
int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT; int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
char *byteptr; char *byteptr;
char byteval; char byteval;
char curval;
byteptr = ClogCtl->shared->page_buffer[slotno] + byteno; 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 || * When replaying transactions during recovery we still need to perform
((*byteptr >> bshift) & CLOG_XACT_BITMASK) == TRANSACTION_STATUS_SUB_COMMITTED || * the two phases of subcommit and then commit. However, some transactions
((*byteptr >> bshift) & CLOG_XACT_BITMASK) == status); * 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 */ /* note this assumes exclusive access to the clog page */
byteval = *byteptr; byteval = *byteptr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment