diff options
Diffstat (limited to 'src/backend/access/transam')
-rw-r--r-- | src/backend/access/transam/twophase.c | 16 | ||||
-rw-r--r-- | src/backend/access/transam/xact.c | 8 | ||||
-rw-r--r-- | src/backend/access/transam/xlog.c | 28 |
3 files changed, 30 insertions, 22 deletions
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 5139af69bbf..3a0b190abcf 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -318,7 +318,7 @@ MarkAsPreparing(TransactionId xid, const char *gid, proc->lxid = (LocalTransactionId) xid; pgxact->xid = xid; pgxact->xmin = InvalidTransactionId; - pgxact->inCommit = false; + pgxact->delayChkpt = false; pgxact->vacuumFlags = 0; proc->pid = 0; proc->backendId = InvalidBackendId; @@ -1034,18 +1034,18 @@ EndPrepare(GlobalTransaction gxact) * odds of a PANIC actually occurring should be very tiny given that we * were able to write the bogus CRC above. * - * We have to set inCommit here, too; otherwise a checkpoint starting + * We have to set delayChkpt here, too; otherwise a checkpoint starting * immediately after the WAL record is inserted could complete without * fsync'ing our state file. (This is essentially the same kind of race * condition as the COMMIT-to-clog-write case that RecordTransactionCommit - * uses inCommit for; see notes there.) + * uses delayChkpt for; see notes there.) * * We save the PREPARE record's location in the gxact for later use by * CheckPointTwoPhase. */ START_CRIT_SECTION(); - MyPgXact->inCommit = true; + MyPgXact->delayChkpt = true; gxact->prepare_lsn = XLogInsert(RM_XACT_ID, XLOG_XACT_PREPARE, records.head); @@ -1086,7 +1086,7 @@ EndPrepare(GlobalTransaction gxact) * checkpoint starting after this will certainly see the gxact as a * candidate for fsyncing. */ - MyPgXact->inCommit = false; + MyPgXact->delayChkpt = false; END_CRIT_SECTION(); @@ -1972,7 +1972,7 @@ RecoverPreparedTransactions(void) * RecordTransactionCommitPrepared * * This is basically the same as RecordTransactionCommit: in particular, - * we must set the inCommit flag to avoid a race condition. + * we must set the delayChkpt flag to avoid a race condition. * * We know the transaction made at least one XLOG entry (its PREPARE), * so it is never possible to optimize out the commit record. @@ -1995,7 +1995,7 @@ RecordTransactionCommitPrepared(TransactionId xid, START_CRIT_SECTION(); /* See notes in RecordTransactionCommit */ - MyPgXact->inCommit = true; + MyPgXact->delayChkpt = true; /* Emit the XLOG commit record */ xlrec.xid = xid; @@ -2053,7 +2053,7 @@ RecordTransactionCommitPrepared(TransactionId xid, TransactionIdCommitTree(xid, nchildren, children); /* Checkpoint can proceed now */ - MyPgXact->inCommit = false; + MyPgXact->delayChkpt = false; END_CRIT_SECTION(); diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 349bdbcd929..a36c8061a2b 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -1001,13 +1001,13 @@ RecordTransactionCommit(void) * RecordTransactionAbort. That's because loss of a transaction abort * is noncritical; the presumption would be that it aborted, anyway. * - * It's safe to change the inCommit flag of our own backend without + * It's safe to change the delayChkpt flag of our own backend without * holding the ProcArrayLock, since we're the only one modifying it. - * This makes checkpoint's determination of which xacts are inCommit a + * This makes checkpoint's determination of which xacts are delayChkpt a * bit fuzzy, but it doesn't matter. */ START_CRIT_SECTION(); - MyPgXact->inCommit = true; + MyPgXact->delayChkpt = true; SetCurrentTransactionStopTimestamp(); @@ -1160,7 +1160,7 @@ RecordTransactionCommit(void) */ if (markXidCommitted) { - MyPgXact->inCommit = false; + MyPgXact->delayChkpt = false; END_CRIT_SECTION(); } diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 411807006ac..2b579f9b727 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6884,8 +6884,8 @@ CreateCheckPoint(int flags) XLogRecData rdata; uint32 freespace; XLogSegNo _logSegNo; - TransactionId *inCommitXids; - int nInCommit; + VirtualTransactionId *vxids; + int nvxids; /* * An end-of-recovery checkpoint is really a shutdown checkpoint, just @@ -7056,9 +7056,14 @@ CreateCheckPoint(int flags) TRACE_POSTGRESQL_CHECKPOINT_START(flags); /* - * Before flushing data, we must wait for any transactions that are - * currently in their commit critical sections. If an xact inserted its - * commit record into XLOG just before the REDO point, then a crash + * In some cases there are groups of actions that must all occur on + * one side or the other of a checkpoint record. Before flushing the + * checkpoint record we must explicitly wait for any backend currently + * performing those groups of actions. + * + * One example is end of transaction, so we must wait for any transactions + * that are currently in commit critical sections. If an xact inserted + * its commit record into XLOG just before the REDO point, then a crash * restart from the REDO point would not replay that record, which means * that our flushing had better include the xact's update of pg_clog. So * we wait till he's out of his commit critical section before proceeding. @@ -7073,21 +7078,24 @@ CreateCheckPoint(int flags) * protected by different locks, but again that seems best on grounds of * minimizing lock contention.) * - * A transaction that has not yet set inCommit when we look cannot be at + * A transaction that has not yet set delayChkpt when we look cannot be at * risk, since he's not inserted his commit record yet; and one that's * already cleared it is not at risk either, since he's done fixing clog * and we will correctly flush the update below. So we cannot miss any * xacts we need to wait for. */ - nInCommit = GetTransactionsInCommit(&inCommitXids); - if (nInCommit > 0) + vxids = GetVirtualXIDsDelayingChkpt(&nvxids); + if (nvxids > 0) { + uint nwaits = 0; + do { pg_usleep(10000L); /* wait for 10 msec */ - } while (HaveTransactionsInCommit(inCommitXids, nInCommit)); + nwaits++; + } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids)); } - pfree(inCommitXids); + pfree(vxids); /* * Get the other info we need for the checkpoint record. |