From: Simon Riggs <simon@2ndQuadrant.com>
To: Alvaro Herrera <alvherre@commandprompt.com>
Cc: Heikki Linnakangas <heikki.linnakangas@enterprisedb.com>
Cc: pgsql-hackers <pgsql-hackers@postgresql.org>
Subject: Re: Subtransaction commits and Hot Standby
Date: Thu, 18 Sep 2008 15:59:19 +0100
Message-ID: <1221749959.3913.2451.camel@ebony.2ndQuadrant> (raw)
In-Reply-To: <20080916141148.GA9229@alvh.no-ip.org>
References: <1221566023.3913.1823.camel@ebony.2ndQuadrant>
<48CFBC34.5010802@enterprisedb.com>
<20080916141148.GA9229@alvh.no-ip.org>
On Tue, 2008-09-16 at 10:11 -0400, Alvaro Herrera wrote:
> I wonder if the improved clog API required to mark multiple
> transactions as committed at once would be also useful to
> TransactionIdCommitTree which is used in regular transaction commit.
I've hacked together this concept patch (WIP).
Not fully tested yet, but it gives a flavour of the API rearrangements
required for atomic clog updates. It passes make check, but that's not
saying enough for a serious review yet. I expect to pick this up again
next week.
--
Simon Riggs www.2ndQuadrant.com
PostgreSQL Training, Services and Support
Attachments:atomic_subxids.v3.patch (text/x-patch, 26.4K) download
Index: src/backend/access/transam/clog.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/access/transam/clog.c,v
retrieving revision 1.47
diff -c -r1.47 clog.c
*** src/backend/access/transam/clog.c 1 Aug 2008 13:16:08 -0000 1.47
--- src/backend/access/transam/clog.c 17 Sep 2008 20:06:15 -0000
***************
*** 80,89 ****
static bool CLOGPagePrecedes(int page1, int page2);
static void WriteZeroPageXlogRec(int pageno);
static void WriteTruncateXlogRec(int pageno);
!
!
! /*
! * Record the final state of a transaction in the commit log.
*
* lsn must be the WAL location of the commit record when recording an async
* commit. For a synchronous commit it can be InvalidXLogRecPtr, since the
--- 80,105 ----
static bool CLOGPagePrecedes(int page1, int page2);
static void WriteZeroPageXlogRec(int pageno);
static void WriteTruncateXlogRec(int pageno);
! static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
! TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno, bool subcommitted);
! static void TransactionIdSetStatusBit(TransactionId xid, XidStatus status,
! XLogRecPtr lsn, int slotno);
!
! /*
! * TransactionIdSetTreeStatus
! *
! * Record the final state of transaction entries in the commit log for
! * a transaction and its subtransaction tree. Take care to ensure this is
! * both atomic and efficient. Prior to 8.4, this capability was provided
! * by the non-atomic TransactionIdSetStatus, which is replaced by this
! * new atomic version.
! *
! * xid is a single xid to set status for. This will typically be
! * the top level transactionid for a top level commit or abort. It can
! * also be a subtransaction when we record transaction aborts.
! *
! * subxids is an array of xids of length nsubxids, representing subtransactions
! * in the tree of xid. In various cases nsubxids may be zero.
*
* lsn must be the WAL location of the commit record when recording an async
* commit. For a synchronous commit it can be InvalidXLogRecPtr, since the
***************
*** 91,107 ****
* should be InvalidXLogRecPtr for abort cases, too.
*
* NB: this is a low-level routine and is NOT the preferred entry point
! * for most uses; TransactionLogUpdate() in transam.c is the intended caller.
*/
void
! TransactionIdSetStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn)
{
- int pageno = TransactionIdToPage(xid);- int byteno = TransactionIdToByte(xid);- int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
int slotno;
! char *byteptr;
! char byteval;
Assert(status == TRANSACTION_STATUS_COMMITTED ||
status == TRANSACTION_STATUS_ABORTED ||
--- 107,221 ----
* should be InvalidXLogRecPtr for abort cases, too.
*
* NB: this is a low-level routine and is NOT the preferred entry point
! * for most uses; functions in in transam.c are the intended callers.
! *
! * Note that no lock requests are made at this level, only lower functions.
! *
! * XXX Think about issuing FADVISE_WILLNEED on pages that we will need,
! * but aren't yet in cache, as well as hinting pages not to fall out of
! * cache yet.
*/
void
! TransactionIdSetTreeStatus(TransactionId xid, int nsubxids,
! TransactionId *subxids, XidStatus status, XLogRecPtr lsn)
! {
! int pageno = TransactionIdToPage(xid); /* get page of parent */
! int i;
! bool subcommitted = false;
!
! /*
! * See how many subxids, if any, are on the same page as the parent, if any.
! */
! for (i = 0; i < nsubxids; i++)
! {
! if (TransactionIdToPage(subxids[i]) != pageno)
! break;
! }
!
! /*
! * Do all items fit on a single page?
! */
! if (i == nsubxids)
! {
! /*
! * Set the parent and any subtransactions on same page as it
! */
! TransactionIdSetPageStatus(xid, nsubxids, subxids, status, lsn,
! pageno, subcommitted);
! }
! else
! {
! int start_subxid = 0;
! int num_on_page = 1;
!
! if (status == TRANSACTION_STATUS_COMMITTED)
! {
! /*
! * If this is a commit then we care about doing this atomically.
! * By here, we know we're updating more than one page of clog,
! * so we must mark entries that are not on the first page so
! * that they show as subcommitted before we then return to
! * update the status to fully committed.
! * We don't mark the first page, because we will be doing that
! * part when we access the first page in our next step.
! */
! TransactionIdSetPageStatus(InvalidTransactionId,
! nsubxids - i, subxids + i,
! TRANSACTION_STATUS_SUB_COMMITTED, lsn, pageno,
! false /* this setting never relevant */);
! }
!
! /*
! * Now set the parent and any subtransactions on same page as it
! */
! TransactionIdSetPageStatus(xid, i, subxids, status, lsn,
! pageno, subcommitted);
!
! /*
! * By now, all subtransactions have been subcommitted, if relevant
! */
! subcommitted = true;
!
! /*
! * Now work through the rest of the subxids one clog page at a time,
! * starting from next subxid.
! */
! start_subxid = i;
! pageno = TransactionIdToPage(subxids[i]);
! for (; i < nsubxids; i++)
! {
! if (TransactionIdToPage(subxids[i]) != pageno)
! {
! TransactionIdSetPageStatus(InvalidTransactionId,
! num_on_page, subxids + start_subxid,
! status, lsn, pageno, true);
! start_subxid = i;
! num_on_page = 1;
! pageno = TransactionIdToPage(subxids[start_subxid]);
! }
! else
! num_on_page++;
! }
!
! /* Write last page */
! TransactionIdSetPageStatus(InvalidTransactionId,
! num_on_page, subxids + start_subxid,
! status, lsn, pageno, true);
! }
! }
!
! /*
! * Record the final state of transaction entries in the commit log for
! * all entries on *one* page only. Atomic only on this page.
! *
! * Otherwise API is same as TransactionIdSetTreeStatus()
! */
! static void
! TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
! TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno, bool subcommitted)
{
int slotno;
! int i;
Assert(status == TRANSACTION_STATUS_COMMITTED ||
status == TRANSACTION_STATUS_ABORTED ||
***************
*** 116,124 ****
* mustn't let it reach disk until we've done the appropriate WAL flush.
* But when lsn is invalid, it's OK to scribble on a page while it is
* write-busy, since we don't care if the update reaches disk sooner than
! * we think. Hence, pass write_ok = XLogRecPtrIsInvalid(lsn).
*/
slotno = SimpleLruReadPage(ClogCtl, pageno, XLogRecPtrIsInvalid(lsn), xid);
byteptr = ClogCtl->shared->page_buffer[slotno] + byteno;
/* Current state should be 0, subcommitted or target state */
--- 230,284 ----
* mustn't let it reach disk until we've done the appropriate WAL flush.
* But when lsn is invalid, it's OK to scribble on a page while it is
* write-busy, since we don't care if the update reaches disk sooner than
! * we think.
*/
slotno = SimpleLruReadPage(ClogCtl, pageno, XLogRecPtrIsInvalid(lsn), xid);
+ + /*+ * If we synch commit more than one xid on this page while write busy+ * we might find that some of the bits go to disk and others don't.+ * That would break atomicity, so if we haven't already subcommitted + * the xids for this commit, we do that first and then come back+ * to start marking commits. If using async commit then we already+ * waited for the write I/O to complete by this point, so nothing to do.+ */+ if (status == TRANSACTION_STATUS_COMMITTED && !subcommitted && XLogRecPtrIsInvalid(lsn))+ {+ for (i = 0; i < nsubxids; i++)+ {+ Assert(ClogCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i]));+ TransactionIdSetStatusBit(subxids[i], + TRANSACTION_STATUS_SUB_COMMITTED, lsn, slotno);+ }+ }+ + /* Set the main transaction id, if any */+ if (TransactionIdIsValid(xid))+ TransactionIdSetStatusBit(xid, status, lsn, slotno);+ + /* Set the subtransactions on this page only */+ for (i = 0; i < nsubxids; i++)+ {+ Assert(ClogCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i]));+ TransactionIdSetStatusBit(subxids[i], status, lsn, slotno);+ }+ + ClogCtl->shared->page_dirty[slotno] = true;+ + LWLockRelease(CLogControlLock);+ }+ + /*+ * Must be called with CLogControlLock held+ */+ static void+ TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, int slotno)+ {+ int byteno = TransactionIdToByte(xid);+ int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;+ char *byteptr;+ char byteval;+
byteptr = ClogCtl->shared->page_buffer[slotno] + byteno;
/* Current state should be 0, subcommitted or target state */
***************
*** 132,139 ****
byteval |= (status << bshift);
*byteptr = byteval;
- ClogCtl->shared->page_dirty[slotno] = true;-
/*
* Update the group LSN if the transaction completion LSN is higher.
*
--- 292,297 ----
***************
*** 149,156 ****
if (XLByteLT(ClogCtl->shared->group_lsn[lsnindex], lsn))
ClogCtl->shared->group_lsn[lsnindex] = lsn;
}
- - LWLockRelease(CLogControlLock);
}
/*
--- 307,312 ----
Index: src/backend/access/transam/transam.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/access/transam/transam.c,v
retrieving revision 1.76
diff -c -r1.76 transam.c
*** src/backend/access/transam/transam.c 26 Mar 2008 18:48:59 -0000 1.76
--- src/backend/access/transam/transam.c 17 Sep 2008 17:54:53 -0000
***************
*** 40,54 ****
/* Local functions */
static XidStatus TransactionLogFetch(TransactionId transactionId);
- static void TransactionLogUpdate(TransactionId transactionId,- XidStatus status, XLogRecPtr lsn);
/* ----------------------------------------------------------------
* Postgres log access method interface
*
* TransactionLogFetch
! * TransactionLogUpdate
* ----------------------------------------------------------------
*/
--- 40,58 ----
/* Local functions */
static XidStatus TransactionLogFetch(TransactionId transactionId);
/* ----------------------------------------------------------------
* Postgres log access method interface
*
* TransactionLogFetch
! *
! * Prior to 8.4, we also had TransactionLogUpdate and
! * TransactionLogMultiUpdate. These have now been merged
! * into a single command TransactionIdSetTreeStatus(),
! * though that is now part of clog.c because of the need
! * for closer integration with clog code to achieve
! * atomic clog updates for subtransactions.
* ----------------------------------------------------------------
*/
***************
*** 100,140 ****
return xidstatus;
}
- /*- * TransactionLogUpdate- *- * Store the new status of a transaction. The commit record LSN must be- * passed when recording an async commit; else it should be InvalidXLogRecPtr.- */- static inline void- TransactionLogUpdate(TransactionId transactionId,- XidStatus status, XLogRecPtr lsn)- {- /*- * update the commit log- */- TransactionIdSetStatus(transactionId, status, lsn);- }- - /*- * TransactionLogMultiUpdate- *- * Update multiple transaction identifiers to a given status.- * Don't depend on this being atomic; it's not.- */- static inline void- TransactionLogMultiUpdate(int nxids, TransactionId *xids,- XidStatus status, XLogRecPtr lsn)- {- int i;- - Assert(nxids != 0);- - for (i = 0; i < nxids; i++)- TransactionIdSetStatus(xids[i], status, lsn);- }- -
/* ----------------------------------------------------------------
* Interface functions
*
--- 104,109 ----
***************
*** 143,154 ****
* ========
* these functions test the transaction status of
* a specified transaction id.
! *
! * TransactionIdCommit
! * TransactionIdAbort
* ========
* these functions set the transaction status
! * of the specified xid.
*
* See also TransactionIdIsInProgress, which once was in this module
* but now lives in procarray.c.
--- 112,125 ----
* ========
* these functions test the transaction status of
* a specified transaction id.
! *
! * TransactionIdCommitTree
! * TransactionIdAsyncCommitTree
! * TransactionIdAbortTree
* ========
* these functions set the transaction status
! * of the specified transaction tree. As of 8.4, these
! * are now atomic so we set the whole tree in a single call.
*
* See also TransactionIdIsInProgress, which once was in this module
* but now lives in procarray.c.
***************
*** 287,374 ****
return false;
}
- - /*- * TransactionIdCommit- * Commits the transaction associated with the identifier.- *- * Note:- * Assumes transaction identifier is valid.- */- void- TransactionIdCommit(TransactionId transactionId)- {- TransactionLogUpdate(transactionId, TRANSACTION_STATUS_COMMITTED,- InvalidXLogRecPtr);- }- - /*- * TransactionIdAsyncCommit- * Same as above, but for async commits. The commit record LSN is needed.- */- void- TransactionIdAsyncCommit(TransactionId transactionId, XLogRecPtr lsn)- {- TransactionLogUpdate(transactionId, TRANSACTION_STATUS_COMMITTED, lsn);- }- - /*- * TransactionIdAbort- * Aborts the transaction associated with the identifier.- *- * Note:- * Assumes transaction identifier is valid.- * No async version of this is needed.- */- void- TransactionIdAbort(TransactionId transactionId)- {- TransactionLogUpdate(transactionId, TRANSACTION_STATUS_ABORTED,- InvalidXLogRecPtr);- }- - /*- * TransactionIdSubCommit- * Marks the subtransaction associated with the identifier as- * sub-committed.- *- * Note:- * No async version of this is needed.- */- void- TransactionIdSubCommit(TransactionId transactionId)- {- TransactionLogUpdate(transactionId, TRANSACTION_STATUS_SUB_COMMITTED,- InvalidXLogRecPtr);- }-
/*
* TransactionIdCommitTree
! * Marks all the given transaction ids as committed.
! *
! * The caller has to be sure that this is used only to mark subcommitted
! * subtransactions as committed, and only *after* marking the toplevel
! * parent as committed. Otherwise there is a race condition against
! * TransactionIdDidCommit.
*/
void
! TransactionIdCommitTree(int nxids, TransactionId *xids)
{
! if (nxids > 0)
! TransactionLogMultiUpdate(nxids, xids, TRANSACTION_STATUS_COMMITTED,
! InvalidXLogRecPtr);
}
/*
* TransactionIdAsyncCommitTree
! * Same as above, but for async commits. The commit record LSN is needed.
*/
void
! TransactionIdAsyncCommitTree(int nxids, TransactionId *xids, XLogRecPtr lsn)
{
! if (nxids > 0)
! TransactionLogMultiUpdate(nxids, xids, TRANSACTION_STATUS_COMMITTED,
! lsn);
}
/*
--- 258,284 ----
return false;
}
/*
* TransactionIdCommitTree
! * Marks all the given transaction ids as committed, atomically.
*/
void
! TransactionIdCommitTree(TransactionId xid, int nxids, TransactionId *xids)
{
! return TransactionIdSetTreeStatus(xid, nxids, xids,
! TRANSACTION_STATUS_COMMITTED, InvalidXLogRecPtr);
}
/*
* TransactionIdAsyncCommitTree
! * Same as above, but for async commits, atomically. The commit record
! * LSN is needed.
*/
void
! TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids, XLogRecPtr lsn)
{
! return TransactionIdSetTreeStatus(xid, nxids, xids,
! TRANSACTION_STATUS_COMMITTED, lsn);
}
/*
***************
*** 379,392 ****
* will consider all the xacts as not-yet-committed anyway.
*/
void
! TransactionIdAbortTree(int nxids, TransactionId *xids)
{
! if (nxids > 0)
! TransactionLogMultiUpdate(nxids, xids, TRANSACTION_STATUS_ABORTED,
! InvalidXLogRecPtr);
}
-
/*
* TransactionIdPrecedes --- is id1 logically < id2?
*/
--- 289,300 ----
* will consider all the xacts as not-yet-committed anyway.
*/
void
! TransactionIdAbortTree(TransactionId xid, int nxids, TransactionId *xids)
{
! TransactionIdSetTreeStatus(xid, nxids, xids,
! TRANSACTION_STATUS_ABORTED, InvalidXLogRecPtr);
}
/*
* TransactionIdPrecedes --- is id1 logically < id2?
*/
Index: src/backend/access/transam/twophase.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/access/transam/twophase.c,v
retrieving revision 1.45
diff -c -r1.45 twophase.c
*** src/backend/access/transam/twophase.c 11 Aug 2008 11:05:10 -0000 1.45
--- src/backend/access/transam/twophase.c 17 Sep 2008 15:01:20 -0000
***************
*** 1745,1753 ****
XLogFlush(recptr);
/* Mark the transaction committed in pg_clog */
! TransactionIdCommit(xid);
! /* to avoid race conditions, the parent must commit first */
! TransactionIdCommitTree(nchildren, children);
/* Checkpoint can proceed now */
MyProc->inCommit = false;
--- 1745,1751 ----
XLogFlush(recptr);
/* Mark the transaction committed in pg_clog */
! TransactionIdCommitTree(xid, nchildren, children);
/* Checkpoint can proceed now */
MyProc->inCommit = false;
***************
*** 1822,1829 ****
* Mark the transaction aborted in clog. This is not absolutely necessary
* but we may as well do it while we are here.
*/
! TransactionIdAbort(xid);
! TransactionIdAbortTree(nchildren, children);
END_CRIT_SECTION();
}
--- 1820,1826 ----
* Mark the transaction aborted in clog. This is not absolutely necessary
* but we may as well do it while we are here.
*/
! TransactionIdAbortTree(xid, nchildren, children);
END_CRIT_SECTION();
}
Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/access/transam/xact.c,v
retrieving revision 1.265
diff -c -r1.265 xact.c
*** src/backend/access/transam/xact.c 11 Aug 2008 11:05:10 -0000 1.265
--- src/backend/access/transam/xact.c 17 Sep 2008 18:00:29 -0000
***************
*** 254,260 ****
static TransactionId RecordTransactionAbort(bool isSubXact);
static void StartTransaction(void);
- static void RecordSubTransactionCommit(void);
static void StartSubTransaction(void);
static void CommitSubTransaction(void);
static void AbortSubTransaction(void);
--- 254,259 ----
***************
*** 952,962 ****
* Now we may update the CLOG, if we wrote a COMMIT record above
*/
if (markXidCommitted)
! {
! TransactionIdCommit(xid);
! /* to avoid race conditions, the parent must commit first */
! TransactionIdCommitTree(nchildren, children);
! }
}
else
{
--- 951,957 ----
* Now we may update the CLOG, if we wrote a COMMIT record above
*/
if (markXidCommitted)
! TransactionIdCommitTree(xid, nchildren, children);
}
else
{
***************
*** 974,984 ****
* flushed before the CLOG may be updated.
*/
if (markXidCommitted)
! {
! TransactionIdAsyncCommit(xid, XactLastRecEnd);
! /* to avoid race conditions, the parent must commit first */
! TransactionIdAsyncCommitTree(nchildren, children, XactLastRecEnd);
! }
}
/*
--- 969,975 ----
* flushed before the CLOG may be updated.
*/
if (markXidCommitted)
! TransactionIdAsyncCommitTree(xid, nchildren, children, XactLastRecEnd);
}
/*
***************
*** 1156,1191 ****
s->maxChildXids = 0;
}
- /*- * RecordSubTransactionCommit- */- static void- RecordSubTransactionCommit(void)- {- TransactionId xid = GetCurrentTransactionIdIfAny();- - /*- * We do not log the subcommit in XLOG; it doesn't matter until the- * top-level transaction commits.- *- * We must mark the subtransaction subcommitted in the CLOG if it had a- * valid XID assigned. If it did not, nobody else will ever know about- * the existence of this subxact. We don't have to deal with deletions- * scheduled for on-commit here, since they'll be reassigned to our parent- * (who might still abort).- */- if (TransactionIdIsValid(xid))- {- /* XXX does this really need to be a critical section? */- START_CRIT_SECTION();- - /* Record subtransaction subcommit */- TransactionIdSubCommit(xid);- - END_CRIT_SECTION();- }- }-
/* ----------------------------------------------------------------
* AbortTransaction stuff
* ----------------------------------------------------------------
--- 1147,1152 ----
***************
*** 1288,1301 ****
* waiting for already-aborted subtransactions. It is OK to do it without
* having flushed the ABORT record to disk, because in event of a crash
* we'd be assumed to have aborted anyway.
- *- * The ordering here isn't critical but it seems best to mark the parent- * first. This assures an atomic transition of all the subtransactions to- * aborted state from the point of view of concurrent- * TransactionIdDidAbort calls.
*/
! TransactionIdAbort(xid);
! TransactionIdAbortTree(nchildren, children);
END_CRIT_SECTION();
--- 1249,1256 ----
* waiting for already-aborted subtransactions. It is OK to do it without
* having flushed the ABORT record to disk, because in event of a crash
* we'd be assumed to have aborted anyway.
*/
! TransactionIdAbortTree(xid, nchildren, children);
END_CRIT_SECTION();
***************
*** 3791,3798 ****
/* Must CCI to ensure commands of subtransaction are seen as done */
CommandCounterIncrement();
! /* Mark subtransaction as subcommitted */
! RecordSubTransactionCommit();
/* Post-commit cleanup */
if (TransactionIdIsValid(s->transactionId))
--- 3746,3757 ----
/* Must CCI to ensure commands of subtransaction are seen as done */
CommandCounterIncrement();
! /*
! * Prior to 8.4 we marked subcommit in clog at this point.
! * We now only perform that step, if required, as part of the
! * atomic update of the whole transaction tree at top level
! * commit or abort.
! */
/* Post-commit cleanup */
if (TransactionIdIsValid(s->transactionId))
***************
*** 4259,4269 ****
TransactionId max_xid;
int i;
- TransactionIdCommit(xid);-
/* Mark committed subtransactions as committed */
sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
! TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
/* Make sure nextXid is beyond any XID mentioned in the record */
max_xid = xid;
--- 4218,4226 ----
TransactionId max_xid;
int i;
/* Mark committed subtransactions as committed */
sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
! TransactionIdCommitTree(xid, xlrec->nsubxacts, sub_xids);
/* Make sure nextXid is beyond any XID mentioned in the record */
max_xid = xid;
***************
*** 4299,4309 ****
TransactionId max_xid;
int i;
- TransactionIdAbort(xid);-
/* Mark subtransactions as aborted */
sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
! TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
/* Make sure nextXid is beyond any XID mentioned in the record */
max_xid = xid;
--- 4256,4264 ----
TransactionId max_xid;
int i;
/* Mark subtransactions as aborted */
sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
! TransactionIdAbortTree(xid, xlrec->nsubxacts, sub_xids);
/* Make sure nextXid is beyond any XID mentioned in the record */
max_xid = xid;
Index: src/include/access/clog.h
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/access/clog.h,v
retrieving revision 1.21
diff -c -r1.21 clog.h
*** src/include/access/clog.h 1 Jan 2008 19:45:56 -0000 1.21
--- src/include/access/clog.h 17 Sep 2008 18:14:35 -0000
***************
*** 32,38 ****
#define NUM_CLOG_BUFFERS 8
! extern void TransactionIdSetStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn);
extern XidStatus TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn);
extern Size CLOGShmemSize(void);
--- 32,39 ----
#define NUM_CLOG_BUFFERS 8
! extern void TransactionIdSetTreeStatus(TransactionId xid, int nsubxids,
! TransactionId *subxids, XidStatus status, XLogRecPtr lsn);
extern XidStatus TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn);
extern Size CLOGShmemSize(void);
Index: src/include/access/transam.h
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/access/transam.h,v
retrieving revision 1.65
diff -c -r1.65 transam.h
*** src/include/access/transam.h 11 Mar 2008 20:20:35 -0000 1.65
--- src/include/access/transam.h 17 Sep 2008 16:43:53 -0000
***************
*** 139,151 ****
extern bool TransactionIdDidCommit(TransactionId transactionId);
extern bool TransactionIdDidAbort(TransactionId transactionId);
extern bool TransactionIdIsKnownCompleted(TransactionId transactionId);
- extern void TransactionIdCommit(TransactionId transactionId);- extern void TransactionIdAsyncCommit(TransactionId transactionId, XLogRecPtr lsn);
extern void TransactionIdAbort(TransactionId transactionId);
! extern void TransactionIdSubCommit(TransactionId transactionId);
! extern void TransactionIdCommitTree(int nxids, TransactionId *xids);
! extern void TransactionIdAsyncCommitTree(int nxids, TransactionId *xids, XLogRecPtr lsn);
! extern void TransactionIdAbortTree(int nxids, TransactionId *xids);
extern bool TransactionIdPrecedes(TransactionId id1, TransactionId id2);
extern bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2);
extern bool TransactionIdFollows(TransactionId id1, TransactionId id2);
--- 139,148 ----
extern bool TransactionIdDidCommit(TransactionId transactionId);
extern bool TransactionIdDidAbort(TransactionId transactionId);
extern bool TransactionIdIsKnownCompleted(TransactionId transactionId);
extern void TransactionIdAbort(TransactionId transactionId);
! extern void TransactionIdCommitTree(TransactionId xid, int nxids, TransactionId *xids);
! extern void TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids, XLogRecPtr lsn);
! extern void TransactionIdAbortTree(TransactionId xid, int nxids, TransactionId *xids);
extern bool TransactionIdPrecedes(TransactionId id1, TransactionId id2);
extern bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2);
extern bool TransactionIdFollows(TransactionId id1, TransactionId id2);
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-patches@postgresql.org
Cc: simon@2ndQuadrant.com, alvherre@commandprompt.com, heikki.linnakangas@enterprisedb.com, pgsql-hackers@postgresql.org
Subject: Re: Subtransaction commits and Hot Standby
In-Reply-To: <1221749959.3913.2451.camel@ebony.2ndQuadrant>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox