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

📄 xact.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 4 页
字号:
/*------------------------------------------------------------------------- * * xact.c *	  top level transaction system support routines * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.156.2.1 2004/08/11 04:08:00 tgl Exp $ * * NOTES *		Transaction aborts can now occur two ways: * *		1)	system dies from some internal cause  (syntax error, etc..) *		2)	user types ABORT * *		These two cases used to be treated identically, but now *		we need to distinguish them.  Why?	consider the following *		two situations: * *				case 1							case 2 *				------							------ *		1) user types BEGIN				1) user types BEGIN *		2) user does something			2) user does something *		3) user does not like what		3) system aborts for some reason *		   she sees and types ABORT * *		In case 1, we want to abort the transaction and return to the *		default state.	In case 2, there may be more commands coming *		our way which are part of the same transaction block and we have *		to ignore these commands until we see a COMMIT transaction or *		ROLLBACK. * *		Internal aborts are now handled by AbortTransactionBlock(), just as *		they always have been, and user aborts are now handled by *		UserAbortTransactionBlock().  Both of them rely on AbortTransaction() *		to do all the real work.  The only difference is what state we *		enter after AbortTransaction() does its work: * *		* AbortTransactionBlock() leaves us in TBLOCK_ABORT and *		* UserAbortTransactionBlock() leaves us in TBLOCK_ENDABORT * *		Low-level transaction abort handling is divided into two phases: *		* AbortTransaction() executes as soon as we realize the transaction *		  has failed.  It should release all shared resources (locks etc) *		  so that we do not delay other backends unnecessarily. *		* CleanupTransaction() executes when we finally see a user COMMIT *		  or ROLLBACK command; it cleans things up and gets us out of *		  the transaction internally.  In particular, we mustn't destroy *		  TopTransactionContext until this point. * *	 NOTES *		The essential aspects of the transaction system are: * *				o  transaction id generation *				o  transaction log updating *				o  memory cleanup *				o  cache invalidation *				o  lock cleanup * *		Hence, the functional division of the transaction code is *		based on which of the above things need to be done during *		a start/commit/abort transaction.  For instance, the *		routine AtCommit_Memory() takes care of all the memory *		cleanup stuff done at commit time. * *		The code is layered as follows: * *				StartTransaction *				CommitTransaction *				AbortTransaction *				CleanupTransaction * *		are provided to do the lower level work like recording *		the transaction status in the log and doing memory cleanup. *		above these routines are another set of functions: * *				StartTransactionCommand *				CommitTransactionCommand *				AbortCurrentTransaction * *		These are the routines used in the postgres main processing *		loop.  They are sensitive to the current transaction block state *		and make calls to the lower level routines appropriately. * *		Support for transaction blocks is provided via the functions: * *				StartTransactionBlock *				CommitTransactionBlock *				AbortTransactionBlock * *		These are invoked only in response to a user "BEGIN WORK", "COMMIT", *		or "ROLLBACK" command.	The tricky part about these functions *		is that they are called within the postgres main loop, in between *		the StartTransactionCommand() and CommitTransactionCommand(). * *		For example, consider the following sequence of user commands: * *		1)		begin *		2)		select * from foo *		3)		insert into foo (bar = baz) *		4)		commit * *		in the main processing loop, this results in the following *		transaction sequence: * *			/	StartTransactionCommand(); *		1) /	ProcessUtility();				<< begin *		   \		StartTransactionBlock(); *			\	CommitTransactionCommand(); * *			/	StartTransactionCommand(); *		2) <	ProcessQuery();					<< select * from foo *			\	CommitTransactionCommand(); * *			/	StartTransactionCommand(); *		3) <	ProcessQuery();					<< insert into foo (bar = baz) *			\	CommitTransactionCommand(); * *			/	StartTransactionCommand(); *		4) /	ProcessUtility();				<< commit *		   \		CommitTransactionBlock(); *			\	CommitTransactionCommand(); * *		The point of this example is to demonstrate the need for *		StartTransactionCommand() and CommitTransactionCommand() to *		be state smart -- they should do nothing in between the calls *		to StartTransactionBlock() and EndTransactionBlock() and *		outside these calls they need to do normal start/commit *		processing. * *		Furthermore, suppose the "select * from foo" caused an abort *		condition.	We would then want to abort the transaction and *		ignore all subsequent commands up to the "commit". *		-cim 3/23/90 * *------------------------------------------------------------------------- */#include "postgres.h"#include <unistd.h>#include <sys/time.h>#include "access/gistscan.h"#include "access/hash.h"#include "access/nbtree.h"#include "access/rtree.h"#include "access/xact.h"#include "catalog/heap.h"#include "catalog/index.h"#include "catalog/namespace.h"#include "commands/async.h"#include "commands/tablecmds.h"#include "commands/trigger.h"#include "commands/user.h"#include "executor/spi.h"#include "libpq/be-fsstubs.h"#include "miscadmin.h"#include "storage/proc.h"#include "storage/sinval.h"#include "storage/smgr.h"#include "utils/guc.h"#include "utils/inval.h"#include "utils/memutils.h"#include "utils/portal.h"#include "utils/catcache.h"#include "utils/relcache.h"#include "pgstat.h"static void AbortTransaction(void);static void AtAbort_Cache(void);static void AtAbort_Locks(void);static void AtAbort_Memory(void);static void AtCleanup_Memory(void);static void AtCommit_Cache(void);static void AtCommit_LocalCache(void);static void AtCommit_Locks(void);static void AtCommit_Memory(void);static void AtStart_Cache(void);static void AtStart_Locks(void);static void AtStart_Memory(void);static void CallEOXactCallbacks(bool isCommit);static void CleanupTransaction(void);static void CommitTransaction(void);static void RecordTransactionAbort(void);static void StartTransaction(void);/* *	global variables holding the current transaction state. */static TransactionStateData CurrentTransactionStateData = {	0,							/* transaction id */	FirstCommandId,				/* command id */	0,							/* scan command id */	0x0,						/* start time */	TRANS_DEFAULT,				/* transaction state */	TBLOCK_DEFAULT				/* transaction block state from the client								 * perspective */};static TransactionState CurrentTransactionState = &CurrentTransactionStateData;/* *	User-tweakable parameters */int			DefaultXactIsoLevel = XACT_READ_COMMITTED;int			XactIsoLevel;bool		DefaultXactReadOnly = false;bool		XactReadOnly;int			CommitDelay = 0;	/* precommit delay in microseconds */int			CommitSiblings = 5; /* number of concurrent xacts needed to								 * sleep *//* * List of add-on end-of-xact callbacks */typedef struct EOXactCallbackItem{	struct EOXactCallbackItem *next;	EOXactCallback callback;	void	   *arg;} EOXactCallbackItem;static EOXactCallbackItem *EOXact_callbacks = NULL;static void (*_RollbackFunc) (void *) = NULL;static void *_RollbackData = NULL;/* ---------------------------------------------------------------- *	transaction state accessors * ---------------------------------------------------------------- */#ifdef NOT_USED/* -------------------------------- *	TransactionFlushEnabled() *	SetTransactionFlushEnabled() * *	These are used to test and set the "TransactionFlushState" *	variable.  If this variable is true (the default), then *	the system will flush all dirty buffers to disk at the end *	of each transaction.   If false then we are assuming the *	buffer pool resides in stable main memory, in which case we *	only do writes as necessary. * -------------------------------- */static int	TransactionFlushState = 1;intTransactionFlushEnabled(void){	return TransactionFlushState;}voidSetTransactionFlushEnabled(bool state){	TransactionFlushState = (state == true);}#endif/* *	IsTransactionState * *	This returns true if we are currently running a query *	within an executing transaction. */boolIsTransactionState(void){	TransactionState s = CurrentTransactionState;	switch (s->state)	{		case TRANS_DEFAULT:			return false;		case TRANS_START:			return true;		case TRANS_INPROGRESS:			return true;		case TRANS_COMMIT:			return true;		case TRANS_ABORT:			return true;	}	/*	 * Shouldn't get here, but lint is not happy with this...	 */	return false;}/* *	IsAbortedTransactionBlockState * *	This returns true if we are currently running a query *	within an aborted transaction block. */boolIsAbortedTransactionBlockState(void){	TransactionState s = CurrentTransactionState;	if (s->blockState == TBLOCK_ABORT)		return true;	return false;}/* *	GetCurrentTransactionId */TransactionIdGetCurrentTransactionId(void){	TransactionState s = CurrentTransactionState;	return s->transactionIdData;}/* *	GetCurrentCommandId */CommandIdGetCurrentCommandId(void){	TransactionState s = CurrentTransactionState;	return s->commandId;}/* *	GetCurrentTransactionStartTime */AbsoluteTimeGetCurrentTransactionStartTime(void){	TransactionState s = CurrentTransactionState;	return s->startTime;}/* *	GetCurrentTransactionStartTimeUsec */AbsoluteTimeGetCurrentTransactionStartTimeUsec(int *msec){	TransactionState s = CurrentTransactionState;	*msec = s->startTimeUsec;	return s->startTime;}/* *	TransactionIdIsCurrentTransactionId * *	During bootstrap, we cheat and say "it's not my transaction ID" even though *	it is.	Along with transam.c's cheat to say that the bootstrap XID is *	already committed, this causes the tqual.c routines to see previously *	inserted tuples as committed, which is what we need during bootstrap. */boolTransactionIdIsCurrentTransactionId(TransactionId xid){	TransactionState s = CurrentTransactionState;	if (AMI_OVERRIDE)	{		Assert(xid == BootstrapTransactionId);		return false;	}	return TransactionIdEquals(xid, s->transactionIdData);}/* *	CommandIdIsCurrentCommandId */boolCommandIdIsCurrentCommandId(CommandId cid){	TransactionState s = CurrentTransactionState;	return (cid == s->commandId) ? true : false;}/* *	CommandCounterIncrement */voidCommandCounterIncrement(void){	TransactionState s = CurrentTransactionState;	s->commandId += 1;	if (s->commandId == FirstCommandId) /* check for overflow */		ereport(ERROR,				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),				 errmsg("cannot have more than 2^32-1 commands in a transaction")));	/* Propagate new command ID into query snapshots, if set */	if (QuerySnapshot)		QuerySnapshot->curcid = s->commandId;	if (SerializableSnapshot)		SerializableSnapshot->curcid = s->commandId;	/*	 * make cache changes visible to me.  AtCommit_LocalCache() instead of	 * AtCommit_Cache() is called here.	 */	AtCommit_LocalCache();	AtStart_Cache();}/* ---------------------------------------------------------------- *						StartTransaction stuff * ---------------------------------------------------------------- *//* *	AtStart_Cache */static voidAtStart_Cache(void){	AcceptInvalidationMessages();}/* *		AtStart_Locks */static voidAtStart_Locks(void){	/*	 * at present, it is unknown to me what belongs here -cim 3/18/90	 *	 * There isn't anything to do at the start of a xact for locks. -mer	 * 5/24/92	 */}/* *	AtStart_Memory */static voidAtStart_Memory(void){	/*

⌨️ 快捷键说明

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