mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Repair two problems with WAL logging of sequence nextvalI() ops, as
per recent pghackers discussion: force a new WAL record at first nextval after a checkpoint, and ensure that xlog is flushed to disk if a nextval record is the only thing emitted by a transaction.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.117 2002/03/06 06:09:21 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.118 2002/03/15 19:20:29 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Transaction aborts can now occur two ways:
|
||||
@ -546,32 +546,48 @@ RecordTransactionCommit(void)
|
||||
xid = GetCurrentTransactionId();
|
||||
|
||||
/*
|
||||
* We needn't write anything in xlog or clog if the transaction was
|
||||
* read-only, which we check by testing if it made any xlog entries.
|
||||
* We only need to log the commit in xlog and clog if the transaction made
|
||||
* any transaction-controlled XLOG entries. (Otherwise, its XID appears
|
||||
* nowhere in permanent storage, so no one will ever care if it
|
||||
* committed.) However, we must flush XLOG to disk if we made any XLOG
|
||||
* entries, whether in or out of transaction control. For example, if we
|
||||
* reported a nextval() result to the client, this ensures that any XLOG
|
||||
* record generated by nextval will hit the disk before we report the
|
||||
* transaction committed.
|
||||
*/
|
||||
if (MyLastRecPtr.xrecoff != 0)
|
||||
if (MyXactMadeXLogEntry)
|
||||
{
|
||||
XLogRecData rdata;
|
||||
xl_xact_commit xlrec;
|
||||
XLogRecPtr recptr;
|
||||
|
||||
BufmgrCommit();
|
||||
|
||||
xlrec.xtime = time(NULL);
|
||||
rdata.buffer = InvalidBuffer;
|
||||
rdata.data = (char *) (&xlrec);
|
||||
rdata.len = SizeOfXactCommit;
|
||||
rdata.next = NULL;
|
||||
|
||||
START_CRIT_SECTION();
|
||||
|
||||
/*
|
||||
* SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
|
||||
*/
|
||||
recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, &rdata);
|
||||
if (MyLastRecPtr.xrecoff != 0)
|
||||
{
|
||||
/* Need to emit a commit record */
|
||||
XLogRecData rdata;
|
||||
xl_xact_commit xlrec;
|
||||
|
||||
xlrec.xtime = time(NULL);
|
||||
rdata.buffer = InvalidBuffer;
|
||||
rdata.data = (char *) (&xlrec);
|
||||
rdata.len = SizeOfXactCommit;
|
||||
rdata.next = NULL;
|
||||
|
||||
/*
|
||||
* XXX SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
|
||||
*/
|
||||
recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, &rdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just flush through last record written by me */
|
||||
recptr = ProcLastRecEnd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sleep before commit! So we can flush more than one commit
|
||||
* Sleep before flush! So we can flush more than one commit
|
||||
* records per single fsync. (The idea is some other backend may
|
||||
* do the XLogFlush while we're sleeping. This needs work still,
|
||||
* because on most Unixen, the minimum select() delay is 10msec or
|
||||
@ -593,15 +609,17 @@ RecordTransactionCommit(void)
|
||||
|
||||
XLogFlush(recptr);
|
||||
|
||||
/* Break the chain of back-links in the XLOG records I output */
|
||||
MyLastRecPtr.xrecoff = 0;
|
||||
|
||||
/* Mark the transaction committed in clog */
|
||||
TransactionIdCommit(xid);
|
||||
/* Mark the transaction committed in clog, if needed */
|
||||
if (MyLastRecPtr.xrecoff != 0)
|
||||
TransactionIdCommit(xid);
|
||||
|
||||
END_CRIT_SECTION();
|
||||
}
|
||||
|
||||
/* Break the chain of back-links in the XLOG records I output */
|
||||
MyLastRecPtr.xrecoff = 0;
|
||||
MyXactMadeXLogEntry = false;
|
||||
|
||||
/* Show myself as out of the transaction in PROC array */
|
||||
MyProc->logRec.xrecoff = 0;
|
||||
|
||||
@ -689,8 +707,11 @@ RecordTransactionAbort(void)
|
||||
TransactionId xid = GetCurrentTransactionId();
|
||||
|
||||
/*
|
||||
* We needn't write anything in xlog or clog if the transaction was
|
||||
* read-only, which we check by testing if it made any xlog entries.
|
||||
* We only need to log the abort in xlog and clog if the transaction made
|
||||
* any transaction-controlled XLOG entries. (Otherwise, its XID appears
|
||||
* nowhere in permanent storage, so no one will ever care if it
|
||||
* committed.) We do not flush XLOG to disk in any case, since the
|
||||
* default assumption after a crash would be that we aborted, anyway.
|
||||
*
|
||||
* Extra check here is to catch case that we aborted partway through
|
||||
* RecordTransactionCommit ...
|
||||
@ -714,11 +735,6 @@ RecordTransactionAbort(void)
|
||||
*/
|
||||
recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata);
|
||||
|
||||
/*
|
||||
* There's no need for XLogFlush here, since the default
|
||||
* assumption would be that we aborted, anyway.
|
||||
*/
|
||||
|
||||
/* Mark the transaction aborted in clog */
|
||||
TransactionIdAbort(xid);
|
||||
|
||||
@ -727,6 +743,8 @@ RecordTransactionAbort(void)
|
||||
|
||||
/* Break the chain of back-links in the XLOG records I output */
|
||||
MyLastRecPtr.xrecoff = 0;
|
||||
MyXactMadeXLogEntry = false;
|
||||
|
||||
/* Show myself as out of the transaction in PROC array */
|
||||
MyProc->logRec.xrecoff = 0;
|
||||
|
||||
|
Reference in New Issue
Block a user