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

回到上一个层面,继续看 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;

 

你可能感兴趣的:(PostgreSQL)