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

📄 xact.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * xact.c *	  top level transaction system support routines * * See src/backend/access/transam/README for more information. * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.257.2.2 2008/04/26 23:35:33 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <time.h>#include <unistd.h>#include "access/multixact.h"#include "access/subtrans.h"#include "access/transam.h"#include "access/twophase.h"#include "access/xact.h"#include "access/xlogutils.h"#include "catalog/namespace.h"#include "commands/async.h"#include "commands/tablecmds.h"#include "commands/trigger.h"#include "executor/spi.h"#include "libpq/be-fsstubs.h"#include "miscadmin.h"#include "pgstat.h"#include "storage/fd.h"#include "storage/lmgr.h"#include "storage/procarray.h"#include "storage/sinvaladt.h"#include "storage/smgr.h"#include "utils/combocid.h"#include "utils/flatfiles.h"#include "utils/guc.h"#include "utils/inval.h"#include "utils/memutils.h"#include "utils/relcache.h"#include "utils/xml.h"/* *	User-tweakable parameters */int			DefaultXactIsoLevel = XACT_READ_COMMITTED;int			XactIsoLevel;bool		DefaultXactReadOnly = false;bool		XactReadOnly;bool		XactSyncCommit = true;int			CommitDelay = 0;	/* precommit delay in microseconds */int			CommitSiblings = 5; /* # concurrent xacts needed to sleep *//* * MyXactAccessedTempRel is set when a temporary relation is accessed. * We don't allow PREPARE TRANSACTION in that case.  (This is global * so that it can be set from heapam.c.) */bool		MyXactAccessedTempRel = false;/* *	transaction states - transaction state from server perspective */typedef enum TransState{	TRANS_DEFAULT,				/* idle */	TRANS_START,				/* transaction starting */	TRANS_INPROGRESS,			/* inside a valid transaction */	TRANS_COMMIT,				/* commit in progress */	TRANS_ABORT,				/* abort in progress */	TRANS_PREPARE				/* prepare in progress */} TransState;/* *	transaction block states - transaction state of client queries * * Note: the subtransaction states are used only for non-topmost * transactions; the others appear only in the topmost transaction. */typedef enum TBlockState{	/* not-in-transaction-block states */	TBLOCK_DEFAULT,				/* idle */	TBLOCK_STARTED,				/* running single-query transaction */	/* transaction block states */	TBLOCK_BEGIN,				/* starting transaction block */	TBLOCK_INPROGRESS,			/* live transaction */	TBLOCK_END,					/* COMMIT received */	TBLOCK_ABORT,				/* failed xact, awaiting ROLLBACK */	TBLOCK_ABORT_END,			/* failed xact, ROLLBACK received */	TBLOCK_ABORT_PENDING,		/* live xact, ROLLBACK received */	TBLOCK_PREPARE,				/* live xact, PREPARE received */	/* subtransaction states */	TBLOCK_SUBBEGIN,			/* starting a subtransaction */	TBLOCK_SUBINPROGRESS,		/* live subtransaction */	TBLOCK_SUBEND,				/* RELEASE received */	TBLOCK_SUBABORT,			/* failed subxact, awaiting ROLLBACK */	TBLOCK_SUBABORT_END,		/* failed subxact, ROLLBACK received */	TBLOCK_SUBABORT_PENDING,	/* live subxact, ROLLBACK received */	TBLOCK_SUBRESTART,			/* live subxact, ROLLBACK TO received */	TBLOCK_SUBABORT_RESTART		/* failed subxact, ROLLBACK TO received */} TBlockState;/* *	transaction state structure */typedef struct TransactionStateData{	TransactionId transactionId;	/* my XID, or Invalid if none */	SubTransactionId subTransactionId;	/* my subxact ID */	char	   *name;			/* savepoint name, if any */	int			savepointLevel; /* savepoint level */	TransState	state;			/* low-level state */	TBlockState blockState;		/* high-level state */	int			nestingLevel;	/* transaction nesting depth */	int			gucNestLevel;	/* GUC context nesting depth */	MemoryContext curTransactionContext;		/* my xact-lifetime context */	ResourceOwner curTransactionOwner;	/* my query resources */	TransactionId *childXids;	/* subcommitted child XIDs, in XID order */	int			nChildXids;		/* # of subcommitted child XIDs */	int			maxChildXids;	/* allocated size of childXids[] */	Oid			prevUser;		/* previous CurrentUserId setting */	bool		prevSecDefCxt;	/* previous SecurityDefinerContext setting */	bool		prevXactReadOnly;		/* entry-time xact r/o state */	struct TransactionStateData *parent;		/* back link to parent */} TransactionStateData;typedef TransactionStateData *TransactionState;/* * CurrentTransactionState always points to the current transaction state * block.  It will point to TopTransactionStateData when not in a * transaction at all, or when in a top-level transaction. */static TransactionStateData TopTransactionStateData = {	0,							/* transaction id */	0,							/* subtransaction id */	NULL,						/* savepoint name */	0,							/* savepoint level */	TRANS_DEFAULT,				/* transaction state */	TBLOCK_DEFAULT,				/* transaction block state from the client								 * perspective */	0,							/* transaction nesting depth */	0,							/* GUC context nesting depth */	NULL,						/* cur transaction context */	NULL,						/* cur transaction resource owner */	NULL,						/* subcommitted child Xids */	0,							/* # of subcommitted child Xids */	0,							/* allocated size of childXids[] */	InvalidOid,					/* previous CurrentUserId setting */	false,						/* previous SecurityDefinerContext setting */	false,						/* entry-time xact r/o state */	NULL						/* link to parent state block */};static TransactionState CurrentTransactionState = &TopTransactionStateData;/* * The subtransaction ID and command ID assignment counters are global * to a whole transaction, so we do not keep them in the state stack. */static SubTransactionId currentSubTransactionId;static CommandId currentCommandId;static bool currentCommandIdUsed;/* * xactStartTimestamp is the value of transaction_timestamp(). * stmtStartTimestamp is the value of statement_timestamp(). * xactStopTimestamp is the time at which we log a commit or abort WAL record. * These do not change as we enter and exit subtransactions, so we don't * keep them inside the TransactionState stack. */static TimestampTz xactStartTimestamp;static TimestampTz stmtStartTimestamp;static TimestampTz xactStopTimestamp;/* * GID to be used for preparing the current transaction.  This is also * global to a whole transaction, so we don't keep it in the state stack. */static char *prepareGID;/* * Some commands want to force synchronous commit. */static bool forceSyncCommit = false;/* * Private context for transaction-abort work --- we reserve space for this * at startup to ensure that AbortTransaction and AbortSubTransaction can work * when we've run out of memory. */static MemoryContext TransactionAbortContext = NULL;/* * List of add-on start- and end-of-xact callbacks */typedef struct XactCallbackItem{	struct XactCallbackItem *next;	XactCallback callback;	void	   *arg;} XactCallbackItem;static XactCallbackItem *Xact_callbacks = NULL;/* * List of add-on start- and end-of-subxact callbacks */typedef struct SubXactCallbackItem{	struct SubXactCallbackItem *next;	SubXactCallback callback;	void	   *arg;} SubXactCallbackItem;static SubXactCallbackItem *SubXact_callbacks = NULL;/* local function prototypes */static void AssignTransactionId(TransactionState s);static void AbortTransaction(void);static void AtAbort_Memory(void);static void AtCleanup_Memory(void);static void AtAbort_ResourceOwner(void);static void AtCommit_LocalCache(void);static void AtCommit_Memory(void);static void AtStart_Cache(void);static void AtStart_Memory(void);static void AtStart_ResourceOwner(void);static void CallXactCallbacks(XactEvent event);static void CallSubXactCallbacks(SubXactEvent event,					 SubTransactionId mySubid,					 SubTransactionId parentSubid);static void CleanupTransaction(void);static void CommitTransaction(void);static TransactionId RecordTransactionAbort(bool isSubXact);static void StartTransaction(void);static void RecordSubTransactionCommit(void);static void StartSubTransaction(void);static void CommitSubTransaction(void);static void AbortSubTransaction(void);static void CleanupSubTransaction(void);static void PushTransaction(void);static void PopTransaction(void);static void AtSubAbort_Memory(void);static void AtSubCleanup_Memory(void);static void AtSubAbort_ResourceOwner(void);static void AtSubCommit_Memory(void);static void AtSubStart_Memory(void);static void AtSubStart_ResourceOwner(void);static void ShowTransactionState(const char *str);static void ShowTransactionStateRec(TransactionState state);static const char *BlockStateAsString(TBlockState blockState);static const char *TransStateAsString(TransState state);/* ---------------------------------------------------------------- *	transaction state accessors * ---------------------------------------------------------------- *//* *	IsTransactionState * *	This returns true if we are inside a valid transaction; that is, *	it is safe to initiate database access, take heavyweight locks, etc. */boolIsTransactionState(void){	TransactionState s = CurrentTransactionState;	/*	 * TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states.  However, we	 * also reject the startup/shutdown states TRANS_START, TRANS_COMMIT,	 * TRANS_PREPARE since it might be too soon or too late within those	 * transition states to do anything interesting.  Hence, the only "valid"	 * state is TRANS_INPROGRESS.	 */	return (s->state == TRANS_INPROGRESS);}/* *	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 ||		s->blockState == TBLOCK_SUBABORT)		return true;	return false;}/* *	GetTopTransactionId * * This will return the XID of the main transaction, assigning one if * it's not yet set.  Be careful to call this only inside a valid xact. */TransactionIdGetTopTransactionId(void){	if (!TransactionIdIsValid(TopTransactionStateData.transactionId))		AssignTransactionId(&TopTransactionStateData);	return TopTransactionStateData.transactionId;}/* *	GetTopTransactionIdIfAny * * This will return the XID of the main transaction, if one is assigned. * It will return InvalidTransactionId if we are not currently inside a * transaction, or inside a transaction that hasn't yet been assigned an XID. */TransactionIdGetTopTransactionIdIfAny(void){	return TopTransactionStateData.transactionId;}/* *	GetCurrentTransactionId * * This will return the XID of the current transaction (main or sub * transaction), assigning one if it's not yet set.  Be careful to call this * only inside a valid xact. */TransactionIdGetCurrentTransactionId(void){	TransactionState s = CurrentTransactionState;	if (!TransactionIdIsValid(s->transactionId))		AssignTransactionId(s);	return s->transactionId;}/* *	GetCurrentTransactionIdIfAny * * This will return the XID of the current sub xact, if one is assigned. * It will return InvalidTransactionId if we are not currently inside a * transaction, or inside a transaction that hasn't been assigned an XID yet. */TransactionIdGetCurrentTransactionIdIfAny(void){	return CurrentTransactionState->transactionId;}/* * AssignTransactionId * * Assigns a new permanent XID to the given TransactionState. * We do not assign XIDs to transactions until/unless this is called. * Also, any parent TransactionStates that don't yet have XIDs are assigned * one; this maintains the invariant that a child transaction has an XID * following its parent's. */static voidAssignTransactionId(TransactionState s){	bool		isSubXact = (s->parent != NULL);	ResourceOwner currentOwner;	/* Assert that caller didn't screw up */	Assert(!TransactionIdIsValid(s->transactionId));	Assert(s->state == TRANS_INPROGRESS);	/*	 * Ensure parent(s) have XIDs, so that a child always has an XID later	 * than its parent.	 */	if (isSubXact && !TransactionIdIsValid(s->parent->transactionId))		AssignTransactionId(s->parent);	/*	 * Generate a new Xid and record it in PG_PROC and pg_subtrans.	 *	 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in	 * shared storage other than PG_PROC; because if there's no room for it in	 * PG_PROC, the subtrans entry is needed to ensure that other backends see	 * the Xid as "running".  See GetNewTransactionId.	 */	s->transactionId = GetNewTransactionId(isSubXact);	if (isSubXact)		SubTransSetParent(s->transactionId, s->parent->transactionId);	/*	 * Acquire lock on the transaction XID.  (We assume this cannot block.) We	 * have to ensure that the lock is assigned to the transaction's own	 * ResourceOwner.	 */	currentOwner = CurrentResourceOwner;	PG_TRY();	{		CurrentResourceOwner = s->curTransactionOwner;		XactLockTableInsert(s->transactionId);	}	PG_CATCH();	{		/* Ensure CurrentResourceOwner is restored on error */		CurrentResourceOwner = currentOwner;		PG_RE_THROW();	}	PG_END_TRY();	CurrentResourceOwner = currentOwner;}/* *	GetCurrentSubTransactionId */SubTransactionIdGetCurrentSubTransactionId(void){	TransactionState s = CurrentTransactionState;	return s->subTransactionId;}/* *	GetCurrentCommandId * * "used" must be TRUE if the caller intends to use the command ID to mark * inserted/updated/deleted tuples.  FALSE means the ID is being fetched * for read-only purposes (ie, as a snapshot validity cutoff).  See * CommandCounterIncrement() for discussion. */CommandIdGetCurrentCommandId(bool used){	/* this is global to a transaction, not subtransaction-local */	if (used)		currentCommandIdUsed = true;	return currentCommandId;}/* *	GetCurrentTransactionStartTimestamp */

⌨️ 快捷键说明

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