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

📄 xact.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
static voidAtCleanup_Memory(void){	Assert(CurrentTransactionState->parent == NULL);	/*	 * 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);	/*	 * Clear the special abort context for next time.	 */	if (TransactionAbortContext != NULL)		MemoryContextResetAndDeleteChildren(TransactionAbortContext);	/*	 * Release all transaction-local memory.	 */	if (TopTransactionContext != NULL)		MemoryContextDelete(TopTransactionContext);	TopTransactionContext = NULL;	CurTransactionContext = NULL;	CurrentTransactionState->curTransactionContext = NULL;}/* ---------------------------------------------------------------- *						CleanupSubTransaction stuff * ---------------------------------------------------------------- *//* * AtSubCleanup_Memory */static voidAtSubCleanup_Memory(void){	TransactionState s = CurrentTransactionState;	Assert(s->parent != NULL);	/* Make sure we're not in an about-to-be-deleted context */	MemoryContextSwitchTo(s->parent->curTransactionContext);	CurTransactionContext = s->parent->curTransactionContext;	/*	 * Clear the special abort context for next time.	 */	if (TransactionAbortContext != NULL)		MemoryContextResetAndDeleteChildren(TransactionAbortContext);	/*	 * Delete the subxact local memory contexts. Its CurTransactionContext can	 * go too (note this also kills CurTransactionContexts from any children	 * of the subxact).	 */	if (s->curTransactionContext)		MemoryContextDelete(s->curTransactionContext);	s->curTransactionContext = NULL;}/* ---------------------------------------------------------------- *						interface routines * ---------------------------------------------------------------- *//* *	StartTransaction */static voidStartTransaction(void){	TransactionState s;	VirtualTransactionId vxid;	/*	 * Let's just make sure the state stack is empty	 */	s = &TopTransactionStateData;	CurrentTransactionState = s;	/*	 * check the current transaction state	 */	if (s->state != TRANS_DEFAULT)		elog(WARNING, "StartTransaction while in %s state",			 TransStateAsString(s->state));	/*	 * set the current transaction state information appropriately during	 * start processing	 */	s->state = TRANS_START;	s->transactionId = InvalidTransactionId;	/* until assigned */	/*	 * Make sure we've freed any old snapshot, and reset xact state variables	 */	FreeXactSnapshot();	XactIsoLevel = DefaultXactIsoLevel;	XactReadOnly = DefaultXactReadOnly;	forceSyncCommit = false;	MyXactAccessedTempRel = false;	/*	 * reinitialize within-transaction counters	 */	s->subTransactionId = TopSubTransactionId;	currentSubTransactionId = TopSubTransactionId;	currentCommandId = FirstCommandId;	currentCommandIdUsed = false;	/*	 * must initialize resource-management stuff first	 */	AtStart_Memory();	AtStart_ResourceOwner();	/*	 * Assign a new LocalTransactionId, and combine it with the backendId to	 * form a virtual transaction id.	 */	vxid.backendId = MyBackendId;	vxid.localTransactionId = GetNextLocalTransactionId();	/*	 * Lock the virtual transaction id before we announce it in the proc array	 */	VirtualXactLockTableInsert(vxid);	/*	 * Advertise it in the proc array.	We assume assignment of	 * LocalTransactionID is atomic, and the backendId should be set already.	 */	Assert(MyProc->backendId == vxid.backendId);	MyProc->lxid = vxid.localTransactionId;	PG_TRACE1(transaction__start, vxid.localTransactionId);	/*	 * set transaction_timestamp() (a/k/a now()).  We want this to be the same	 * as the first command's statement_timestamp(), so don't do a fresh	 * GetCurrentTimestamp() call (which'd be expensive anyway).  Also, mark	 * xactStopTimestamp as unset.	 */	xactStartTimestamp = stmtStartTimestamp;	xactStopTimestamp = 0;	pgstat_report_xact_timestamp(xactStartTimestamp);	/*	 * initialize current transaction state fields	 *	 * note: prevXactReadOnly is not used at the outermost level	 */	s->nestingLevel = 1;	s->gucNestLevel = 1;	s->childXids = NULL;	s->nChildXids = 0;	s->maxChildXids = 0;	GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);	/* SecurityDefinerContext should never be set outside a transaction */	Assert(!s->prevSecDefCxt);	/*	 * initialize other subsystems for new transaction	 */	AtStart_GUC();	AtStart_Inval();	AtStart_Cache();	AfterTriggerBeginXact();	/*	 * done with start processing, set current transaction state to "in	 * progress"	 */	s->state = TRANS_INPROGRESS;	ShowTransactionState("StartTransaction");}/* *	CommitTransaction * * NB: if you change this routine, better look at PrepareTransaction too! */static voidCommitTransaction(void){	TransactionState s = CurrentTransactionState;	TransactionId latestXid;	ShowTransactionState("CommitTransaction");	/*	 * check the current transaction state	 */	if (s->state != TRANS_INPROGRESS)		elog(WARNING, "CommitTransaction while in %s state",			 TransStateAsString(s->state));	Assert(s->parent == NULL);	/*	 * Do pre-commit processing (most of this stuff requires database access,	 * and in fact could still cause an error...)	 *	 * It is possible for CommitHoldablePortals to invoke functions that queue	 * deferred triggers, and it's also possible that triggers create holdable	 * cursors.  So we have to loop until there's nothing left to do.	 */	for (;;)	{		/*		 * Fire all currently pending deferred triggers.		 */		AfterTriggerFireDeferred();		/*		 * Convert any open holdable cursors into static portals.  If there		 * weren't any, we are done ... otherwise loop back to check if they		 * queued deferred triggers.  Lather, rinse, repeat.		 */		if (!CommitHoldablePortals())			break;	}	/* Now we can shut down the deferred-trigger manager */	AfterTriggerEndXact(true);	/* Close any open regular cursors */	AtCommit_Portals();	/*	 * Let ON COMMIT management do its thing (must happen after closing	 * cursors, to avoid dangling-reference problems)	 */	PreCommit_on_commit_actions();	/* close large objects before lower-level cleanup */	AtEOXact_LargeObject(true);	/* NOTIFY commit must come before lower-level cleanup */	AtCommit_Notify();	/*	 * Update flat files if we changed pg_database, pg_authid or	 * pg_auth_members.  This should be the last step before commit.	 */	AtEOXact_UpdateFlatFiles(true);	/* Prevent cancel/die interrupt while cleaning up */	HOLD_INTERRUPTS();	/*	 * set the current transaction state information appropriately during	 * commit processing	 */	s->state = TRANS_COMMIT;	/*	 * Here is where we really truly commit.	 */	latestXid = RecordTransactionCommit();	PG_TRACE1(transaction__commit, MyProc->lxid);	/*	 * Let others know about no transaction in progress by me. Note that this	 * must be done _before_ releasing locks we hold and _after_	 * RecordTransactionCommit.	 */	ProcArrayEndTransaction(MyProc, latestXid);	/*	 * This is all post-commit cleanup.  Note that if an error is raised here,	 * it's too late to abort the transaction.  This should be just	 * noncritical resource releasing.	 *	 * The ordering of operations is not entirely random.  The idea is:	 * release resources visible to other backends (eg, files, buffer pins);	 * then release locks; then release backend-local resources. We want to	 * release locks at the point where any backend waiting for us will see	 * our transaction as being fully cleaned up.	 *	 * Resources that can be associated with individual queries are handled by	 * the ResourceOwner mechanism.  The other calls here are for backend-wide	 * state.	 */	CallXactCallbacks(XACT_EVENT_COMMIT);	ResourceOwnerRelease(TopTransactionResourceOwner,						 RESOURCE_RELEASE_BEFORE_LOCKS,						 true, true);	/* Check we've released all buffer pins */	AtEOXact_Buffers(true);	/* Clean up the relation cache */	AtEOXact_RelationCache(true);	/*	 * Make catalog changes visible to all backends.  This has to happen after	 * relcache references are dropped (see comments for	 * AtEOXact_RelationCache), but before locks are released (if anyone is	 * waiting for lock on a relation we've modified, we want them to know	 * about the catalog change before they start using the relation).	 */	AtEOXact_Inval(true);	/*	 * Likewise, dropping of files deleted during the transaction is best done	 * after releasing relcache and buffer pins.  (This is not strictly	 * necessary during commit, since such pins should have been released	 * already, but this ordering is definitely critical during abort.)	 */	smgrDoPendingDeletes(true);	AtEOXact_MultiXact();	ResourceOwnerRelease(TopTransactionResourceOwner,						 RESOURCE_RELEASE_LOCKS,						 true, true);	ResourceOwnerRelease(TopTransactionResourceOwner,						 RESOURCE_RELEASE_AFTER_LOCKS,						 true, true);	/* Check we've released all catcache entries */	AtEOXact_CatCache(true);	AtEOXact_GUC(true, 1);	AtEOXact_SPI(true);	AtEOXact_xml();	AtEOXact_on_commit_actions(true);	AtEOXact_Namespace(true);	/* smgrcommit already done */	AtEOXact_Files();	AtEOXact_ComboCid();	AtEOXact_HashTables(true);	AtEOXact_PgStat(true);	pgstat_report_xact_timestamp(0);	CurrentResourceOwner = NULL;	ResourceOwnerDelete(TopTransactionResourceOwner);	s->curTransactionOwner = NULL;	CurTransactionResourceOwner = NULL;	TopTransactionResourceOwner = NULL;	AtCommit_Memory();	s->transactionId = InvalidTransactionId;	s->subTransactionId = InvalidSubTransactionId;	s->nestingLevel = 0;	s->gucNestLevel = 0;	s->childXids = NULL;	s->nChildXids = 0;	s->maxChildXids = 0;	/*	 * done with commit processing, set current transaction state back to	 * default	 */	s->state = TRANS_DEFAULT;	RESUME_INTERRUPTS();}/* *	PrepareTransaction * * NB: if you change this routine, better look at CommitTransaction too! */static voidPrepareTransaction(void){	TransactionState s = CurrentTransactionState;	TransactionId xid = GetCurrentTransactionId();	GlobalTransaction gxact;	TimestampTz prepared_at;	ShowTransactionState("PrepareTransaction");	/*	 * check the current transaction state	 */	if (s->state != TRANS_INPROGRESS)		elog(WARNING, "PrepareTransaction while in %s state",			 TransStateAsString(s->state));	Assert(s->parent == NULL);	/*	 * Do pre-commit processing (most of this stuff requires database access,	 * and in fact could still cause an error...)	 *	 * It is possible for PrepareHoldablePortals to invoke functions that	 * queue deferred triggers, and it's also possible that triggers create	 * holdable cursors.  So we have to loop until there's nothing left to do.	 */	for (;;)	{		/*		 * Fire all currently pending deferred triggers.		 */		AfterTriggerFireDeferred();		/*		 * Convert any open holdable cursors into static portals.  If there		 * weren't any, we are done ... otherwise loop back to check if they		 * queued deferred triggers.  Lather, rinse, repeat.		 */		if (!PrepareHoldablePortals())			break;	}	/* Now we can shut down the deferred-trigger manager */	AfterTriggerEndXact(true);	/* Close any open regular cursors */	AtCommit_Portals();	/*	 * Let ON COMMIT management do its thing (must happen after closing	 * cursors, to avoid dangling-reference problems)	 */	PreCommit_on_commit_actions();	/* close large objects before lower-level cleanup */	AtEOXact_LargeObject(true);	/* NOTIFY and flatfiles will be handled below */	/*	 * Don't allow PREPARE TRANSACTION if we've accessed a temporary table	 * in this transaction.  Having the prepared xact hold locks on another	 * backend's temp table seems a bad idea --- for instance it would prevent	 * the backend from exiting.  There are other problems too, such as how	 * to clean up the source backend's local buffers and ON COMMIT state	 * if the prepared xact includes a DROP of a temp table.	 *	 * We must check this after executing any ON COMMIT actions, because	 * they might still access a temp relation.	 *	 * XXX In principle this could be relaxed to allow some useful special	 * cases, such as a temp table created and dropped all within the	 * transaction.  That seems to require much more bookkeeping though.	 */	if (MyXactAccessedTempRel)		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("cannot PREPARE a transaction that has operated on temporary tables")));	/* Prevent cancel/die interrupt while cleaning up */	HOLD_INTERRUPTS();	/*	 * set the current transaction state information appropriately during	 * prepare processing	 */	s->state = TRANS_PREPARE;	prepared_at = GetCurrentTimestamp();	/* Tell bufmgr and smgr to prepare for commit */	BufmgrCommit();	/*	 * Reserve the GID for this transaction. This could fail if the requested

⌨️ 快捷键说明

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