您的位置:首页 > 数据库

PostgreSQL在何处处理 sql查询之三十一

2013-05-29 16:41 441 查看
回到上一个层面,继续看 PortalStart的处理:

void
PortalStart(Portal portal, ParamListInfo params,
int eflags, bool use_active_snapshot)
{
...
PG_TRY();
{
...

/*
* Determine the portal execution strategy
*/
portal->strategy = ChoosePortalStrategy(portal->stmts);

/*
* Fire her up according to the strategy
*/
switch (portal->strategy)
{
case PORTAL_ONE_SELECT:

/* Must set snapshot before starting executor. */
                if (use_active_snapshot)
PushActiveSnapshot(GetActiveSnapshot());
else
PushActiveSnapshot(GetTransactionSnapshot());

/*
* Create QueryDesc in portal's context; for the moment, set
* the destination to DestNone.
*/
queryDesc = CreateQueryDesc((PlannedStmt *) linitial(portal->stmts,
portal->sourceText,
GetActiveSnapshot(),
InvalidSnapshot,
None_Receiver,
params,
0);

/*
* If it's a scrollable cursor, executor needs to support
* REWIND and backwards scan, as well as whatever the caller
* might've asked for.
*/
if (portal->cursorOptions & CURSOR_OPT_SCROLL)
myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD;
else
myeflags = eflags;

/*
* Call ExecutorStart to prepare the plan for execution
*/
ExecutorStart(queryDesc, myeflags);

/*
* This tells PortalCleanup to shut down the executor
*/
portal->queryDesc = queryDesc;

/*
* Remember tuple descriptor (computed by ExecutorStart)
*/
portal->tupDesc = queryDesc->tupDesc;

/*
* Reset cursor position data to "start of query"
*/
portal->atStart = true;
portal->atEnd = false;    /* allow fetches */
portal->portalPos = 0;
portal->posOverflow = false;

PopActiveSnapshot();
break;

case PORTAL_ONE_RETURNING:
case PORTAL_ONE_MOD_WITH:

...
break;

case PORTAL_UTIL_SELECT:
...
break;

case PORTAL_MULTI_QUERY:
/* Need do nothing now */
portal->tupDesc = NULL;
break;
}
}
PG_CATCH();
{
...
PG_RE_THROW();
}
PG_END_TRY();
...
}


由之前的分析可以知道,满足 case PORTAL_ONE_SELECT 的条件,下面再看

use_active_snapshot,回溯上层:

static void
exec_simple_query(const char *query_string)
{
...
foreach(parsetree_item, parsetree_list)
{
...
/*
* Set up a snapshot if parse analysis/planning will need one.
*/
if (analyze_requires_snapshot(parsetree))
{
PushActiveSnapshot(GetTransactionSnapshot());
snapshot_set = true;
}
...
PortalStart(portal, NULL, 0, snapshot_set);
}
...
}


可见,snapshot 还是要搞的。简言之,snapshot 是为了MVCC控制:

typedef struct SnapshotData
{
SnapshotSatisfiesFunc satisfies;    /* tuple test function */

/*
* The remaining fields are used only for MVCC snapshots, and are normally
* just zeroes in special snapshots.  (But xmin and xmax are used
* specially by HeapTupleSatisfiesDirty.)
*
* An MVCC snapshot can never see the effects of XIDs >= xmax. It can see
* the effects of all older XIDs except those listed in the snapshot. xmin
* is stored as an optimization to avoid needing to search the XID arrays
* for most tuples.
*/
TransactionId xmin;            /* all XID < xmin are visible to me */
TransactionId xmax;            /* all XID >= xmax are invisible to me */
TransactionId *xip;            /* array of xact IDs in progress */
uint32        xcnt;            /* # of xact ids in xip[] */
/* note: all ids in xip[] satisfy xmin <= xip[i] < xmax */
int32        subxcnt;        /* # of xact ids in subxip[] */
TransactionId *subxip;        /* array of subxact IDs in progress */
bool        suboverflowed;    /* has the subxip array overflowed? */
bool        takenDuringRecovery;    /* recovery-shaped snapshot? */
bool        copied;            /* false if it's a static snapshot */

/*
* note: all ids in subxip[] are >= xmin, but we don't bother filtering
* out any that are >= xmax
*/
CommandId    curcid;            /* in my xact, CID < curcid are visible */
uint32        active_count;    /* refcount on ActiveSnapshot stack */
uint32        regd_count;        /* refcount on RegisteredSnapshotList */
} SnapshotData;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: