⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xact.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * We shouldn't have a transaction context already.	 */	Assert(TopTransactionContext == NULL);	/*	 * Create a toplevel context for the transaction, and make it active.	 */	TopTransactionContext =		AllocSetContextCreate(TopMemoryContext,							  "TopTransactionContext",							  ALLOCSET_DEFAULT_MINSIZE,							  ALLOCSET_DEFAULT_INITSIZE,							  ALLOCSET_DEFAULT_MAXSIZE);	MemoryContextSwitchTo(TopTransactionContext);}/* ---------------------------------------------------------------- *						CommitTransaction stuff * ---------------------------------------------------------------- *//* *	RecordTransactionCommit */voidRecordTransactionCommit(void){	/*	 * If we made neither any XLOG entries nor any temp-rel updates, we	 * can omit recording the transaction commit at all.	 */	if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate)	{		TransactionId xid = GetCurrentTransactionId();		bool		madeTCentries;		XLogRecPtr	recptr;		/* Tell bufmgr and smgr to prepare for commit */		BufmgrCommit();		START_CRIT_SECTION();		/*		 * If our transaction made any transaction-controlled XLOG entries,		 * we need to lock out checkpoint start between writing our XLOG		 * record and updating pg_clog.  Otherwise it is possible for the		 * checkpoint to set REDO after the XLOG record but fail to flush the		 * pg_clog update to disk, leading to loss of the transaction commit		 * if we crash a little later.  Slightly klugy fix for problem		 * discovered 2004-08-10.		 *		 * (If it made no transaction-controlled XLOG entries, its XID		 * appears nowhere in permanent storage, so no one else will ever care		 * if it committed; so it doesn't matter if we lose the commit flag.)		 *		 * Note we only need a shared lock.		 */		madeTCentries = (MyLastRecPtr.xrecoff != 0);		if (madeTCentries)			LWLockAcquire(CheckpointStartLock, LW_SHARED);		/*		 * We only need to log the commit in XLOG if the transaction made		 * any transaction-controlled XLOG entries.		 */		if (madeTCentries)		{			/* 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;		}		/*		 * We must flush our XLOG entries 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 (MyXactMadeXLogEntry)		{			/*			 * 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 more, which is way too long.)			 *			 * We do not sleep if enableFsync is not turned on, nor if there			 * are fewer than CommitSiblings other backends with active			 * transactions.			 */			if (CommitDelay > 0 && enableFsync &&				CountActiveBackends() >= CommitSiblings)			{				struct timeval delay;				delay.tv_sec = 0;				delay.tv_usec = CommitDelay;				(void) select(0, NULL, NULL, NULL, &delay);			}			XLogFlush(recptr);		}		/*		 * We must mark the transaction committed in clog if its XID		 * appears either in permanent rels or in local temporary rels. We		 * test this by seeing if we made transaction-controlled entries		 * *OR* local-rel tuple updates.  Note that if we made only the		 * latter, we have not emitted an XLOG record for our commit, and		 * so in the event of a crash the clog update might be lost.  This		 * is okay because no one else will ever care whether we		 * committed.		 */		if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)			TransactionIdCommit(xid);		/* Unlock checkpoint lock if we acquired it */		if (madeTCentries)			LWLockRelease(CheckpointStartLock);		END_CRIT_SECTION();	}	/* Break the chain of back-links in the XLOG records I output */	MyLastRecPtr.xrecoff = 0;	MyXactMadeXLogEntry = false;	MyXactMadeTempRelUpdate = false;	/* Show myself as out of the transaction in PGPROC array */	MyProc->logRec.xrecoff = 0;}/* *	AtCommit_Cache */static voidAtCommit_Cache(void){	/*	 * Clean up the relation cache.	 */	AtEOXact_RelationCache(true);	/*	 * Make catalog changes visible to all backends.	 */	AtEOXactInvalidationMessages(true);}/* *	AtCommit_LocalCache */static voidAtCommit_LocalCache(void){	/*	 * Make catalog changes visible to me for the next command.	 */	CommandEndInvalidationMessages(true);}/* *	AtCommit_Locks */static voidAtCommit_Locks(void){	/*	 * XXX What if ProcReleaseLocks fails?	(race condition?)	 *	 * Then you're up a creek! -mer 5/24/92	 */	ProcReleaseLocks(true);}/* *	AtCommit_Memory */static voidAtCommit_Memory(void){	/*	 * Now that we're "out" of a transaction, have the system allocate	 * things in the top memory context instead of per-transaction	 * contexts.	 */	MemoryContextSwitchTo(TopMemoryContext);	/*	 * Release all transaction-local memory.	 */	Assert(TopTransactionContext != NULL);	MemoryContextDelete(TopTransactionContext);	TopTransactionContext = NULL;}/* ---------------------------------------------------------------- *						AbortTransaction stuff * ---------------------------------------------------------------- *//* *	RecordTransactionAbort */static voidRecordTransactionAbort(void){	/*	 * If we made neither any transaction-controlled XLOG entries nor any	 * temp-rel updates, we can omit recording the transaction abort at	 * all. No one will ever care that it aborted.	 */	if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)	{		TransactionId xid = GetCurrentTransactionId();		/*		 * Catch the scenario where we aborted partway through		 * RecordTransactionCommit ...		 */		if (TransactionIdDidCommit(xid))			elog(PANIC, "cannot abort transaction %u, it was already committed", xid);		START_CRIT_SECTION();		/*		 * We only need to log the abort in XLOG if the transaction made		 * any transaction-controlled XLOG entries.  (Otherwise, its XID		 * appears nowhere in permanent storage, so no one else 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.		 * For the same reason, we don't need to worry about interlocking		 * against checkpoint start.		 */		if (MyLastRecPtr.xrecoff != 0)		{			XLogRecData rdata;			xl_xact_abort xlrec;			XLogRecPtr	recptr;			xlrec.xtime = time(NULL);			rdata.buffer = InvalidBuffer;			rdata.data = (char *) (&xlrec);			rdata.len = SizeOfXactAbort;			rdata.next = NULL;			/*			 * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP			 */			recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata);		}		/*		 * Mark the transaction aborted in clog.  This is not absolutely		 * necessary but we may as well do it while we are here.		 */		TransactionIdAbort(xid);		END_CRIT_SECTION();	}	/* Break the chain of back-links in the XLOG records I output */	MyLastRecPtr.xrecoff = 0;	MyXactMadeXLogEntry = false;	MyXactMadeTempRelUpdate = false;	/* Show myself as out of the transaction in PGPROC array */	MyProc->logRec.xrecoff = 0;}/* *	AtAbort_Cache */static voidAtAbort_Cache(void){	AtEOXact_RelationCache(false);	AtEOXactInvalidationMessages(false);}/* *	AtAbort_Locks */static voidAtAbort_Locks(void){	/*	 * XXX What if ProcReleaseLocks() fails?  (race condition?)	 *	 * Then you're up a creek without a paddle! -mer	 */	ProcReleaseLocks(false);}/* *	AtAbort_Memory */static voidAtAbort_Memory(void){	/*	 * Make sure we are in a valid context (not a child of	 * TopTransactionContext...).  Note that it is possible for this code	 * to be called when we aren't in a transaction at all; go directly to	 * TopMemoryContext in that case.	 */	if (TopTransactionContext != NULL)	{		MemoryContextSwitchTo(TopTransactionContext);		/*		 * We do not want to destroy the transaction's global state yet,		 * so we can't free any memory here.		 */	}	else		MemoryContextSwitchTo(TopMemoryContext);}/* ---------------------------------------------------------------- *						CleanupTransaction stuff * ---------------------------------------------------------------- *//* *	AtCleanup_Memory */static voidAtCleanup_Memory(void){	/*	 * Now that we're "out" of a transaction, have the system allocate	 * things in the top memory context instead of per-transaction	 * contexts.	 */	MemoryContextSwitchTo(TopMemoryContext);	/*	 * Release all transaction-local memory.	 */	if (TopTransactionContext != NULL)		MemoryContextDelete(TopTransactionContext);	TopTransactionContext = NULL;}/* ---------------------------------------------------------------- *						interface routines * ---------------------------------------------------------------- *//* *	StartTransaction */static voidStartTransaction(void){	TransactionState s = CurrentTransactionState;	/*	 * check the current transaction state	 */	if (s->state != TRANS_DEFAULT)		elog(WARNING, "StartTransaction and not in default state");	/*	 * set the current transaction state information appropriately during	 * start processing	 */	s->state = TRANS_START;	/*	 * Make sure we've freed any old snapshot, and reset xact state variables	 */	FreeXactSnapshot();	XactIsoLevel = DefaultXactIsoLevel;	XactReadOnly = DefaultXactReadOnly;	/*	 * generate a new transaction id	 */	s->transactionIdData = GetNewTransactionId();	XactLockTableInsert(s->transactionIdData);	/*	 * initialize current transaction state fields	 */	s->commandId = FirstCommandId;	s->startTime = GetCurrentAbsoluteTimeUsec(&(s->startTimeUsec));	/*	 * initialize the various transaction subsystems	 */	AtStart_Memory();	AtStart_Cache();	AtStart_Locks();	/*	 * Tell the trigger manager to we're starting a transaction	 */	DeferredTriggerBeginXact();	/*	 * done with start processing, set current transaction state to "in	 * progress"	 */	s->state = TRANS_INPROGRESS;}/* *	CommitTransaction */static voidCommitTransaction(void){	TransactionState s = CurrentTransactionState;	/*	 * check the current transaction state	 */	if (s->state != TRANS_INPROGRESS)		elog(WARNING, "CommitTransaction and not in in-progress state");	/*	 * Tell the trigger manager that this transaction is about to be	 * committed. He'll invoke all trigger deferred until XACT before we	 * really start on committing the transaction.	 */	DeferredTriggerEndXact();	/*	 * Similarly, let ON COMMIT management do its thing before we start to	 * commit.	 */	PreCommit_on_commit_actions();	/* Prevent cancel/die interrupt while cleaning up */	HOLD_INTERRUPTS();	/*	 * set the current transaction state information appropriately during	 * the abort processing	 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -