gqinvs 发表于 2016-11-21 07:42:29

PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询一:开启事务

在《PostgreSQL服务过程中的那些事二:pg服务进程处理简单查询概览》里话说以下面的例子对简单查询分支进行讨论,并给出了简单查询方法调用序列,下面就从这儿开始,先回顾一下上节点内容。
进入简单查询分支处理方法exec_simple_query后的处理基本上涵盖了《数据库系统实现》这本书里的内容。处理量相当大,先根据流程图概览一下处理过程。为了减小图的大小,把PostgresMain以前的调用流程略了。在以后讨论简单查询时PostgresMain以前的调用流程也省略了,要回顾可参见《PostgreSQL服务过程中的那些事二:pg服务进程处理简单查询概览》里的“Postgres服务进程处理请求的无限循环调用序列图”。



处理简单查询方法exec_simple_query调用序列图
主要的处理过程是先调用start_xact_command方法开启一个事务,再用pg_parse_query方法用词法语法解析工具把查询命令解析为解析树parsetree,根据需要调用PushActiveSnapshot方法搞一个快照,调用pg_analyze_and_rewrite方法分析、根据规则重写解析树为查询树querytree,调用pg_plan_queries方法把查询树转换到执行计划树plantree,在调用相应方法创建portal和在postal中执行执行计划树并给客户端发回结果。然后退出当前事务,清理内存。
 
1
现在描述这个例子:数据库TEST里有表TEST1、TEST2,现在客户端发出查询“selectcname, comp from test1, test2 where test1.id=test2.id;”。建表的语句在下面。
createtable test1 (ID numeric(10), cname varchar(30));
createtable test2 (ID numeric(10), comp varchar(30));
postgres服务进程分析了查询指令后走了简查查询分支exec_simple_query。
 
         再看一下exec_simple_query方法的简化流程图



exec_simple_query方法的简化流程图
  
2
进了excu_simple_query分支的第一件事就是开启一个事务命令,pg里所有查询都要在事务里进行。下面是开启事务的调用序列图。



Postgres服务进程简查之开始事务调用序列图
 
         上图大红色方框中显示了启动事物的相关的相关处理,进入StartTransaction方法后,使TransactionStateData *类型静态全局变量CurrentTransactionState指向TransactionStateData类型静态全局变量TopTransactionStateData,在CurrentTransactionState设置当前事务状态,记录当前事务ID和当前命令ID。然后调用AtStart_Memory方法创建内存上下文"TransactionAbortContext"和"TopTransactionContext",接着调用AtStart_ResourceOwner方法在内存上下文"TopMemoryContext"中创建资源属主ResourceOwnerData类型变量curTransationOwner,并让CurrentTransactionState的ResourceOwnerData*类型成员curTransactionOwner指向该变量。用以上建立的结构管理该事务涉及到资源。描述着比较难理清关系,看下面的图吧。



记录事务状态及管理事务资源的相关结构图
    从图中看见事务相关的资源属主ResourceOwnerData管理的事务资源包括关系内存缓存、系统表缓存catcache、关系模式缓存relcache、执行计划缓存plancache、查询命令相关元组描述符缓存tupdesc、事务相关快照以及打开的临时文件等。
 
事务状态及管理事务资源的相关结构见下面:
 
/*
 *  transactionstate structure
 */
typedef struct TransactionStateData
{
    TransactionId transactionId;    /* my XID, or Invalid if none */
    SubTransactionId subTransactionId;  /* my subxactID */
    char      *name;           /* savepointname, if any*/
    int         savepointLevel; /* savepointlevel */
    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;   /* subcommittedchild XIDs, in XID order */
    int         nChildXids;     /* # of subcommittedchildXIDs */
    int         maxChildXids;   /* allocated size of childXids[]*/
    Oid         prevUser;       /* previous CurrentUserId setting*/
    int         prevSecContext; /* previous SecurityRestrictionContext */
    bool        prevXactReadOnly;       /* entry-time xactr/ostate */
    bool        startedInRecovery;      /* did we start in recovery? */
    struct TransactionStateData *parent;        /* back link to parent */
} TransactionStateData;
 
typedef TransactionStateData *TransactionState;
 
/*
 * CurrentTransactionState always points to thecurrent transaction state
 * block. It will point to TopTransactionStateData when not in a
 * transaction at all, or when in a top-leveltransaction.
 */
static TransactionStateData TopTransactionStateData= {
    0,                          /* transaction id */
    0,                          /* subtransactionid */
    NULL,                       /* savepointname */
    0,                          /* savepointlevel */
    TRANS_DEFAULT,              /* transaction state */
    TBLOCK_DEFAULT,             /* transaction block state fromthe client
                                 * perspective */
    0,                          /* transaction nesting depth */
    0,                          /* GUC context nesting depth */
    NULL,                       /* cur transaction context */
    NULL,                       /* cur transaction resource owner*/
    NULL,                       /* subcommittedchild Xids*/
    0,                          /* # of subcommittedchild Xids*/
    0,                          /* allocated size of childXids[]*/
    InvalidOid,                 /* previous CurrentUserId setting*/
    0,                          /* previousSecurityRestrictionContext */
    false,                      /* entry-time xactr/ostate */
    false,                      /* startedInRecovery */
    NULL                        /* link to parent state block */
};
 
static TransactionState CurrentTransactionState=&TopTransactionStateData;
 
3
         接着调用VirtualXactLockTableInsert方法给该事务一个VirtualTransactionId(这个类型是把pg服务进程ID和该进程上的事务ID关联起来的结构)类型的虚拟事务ID:VXID,并加锁。VirtualTransactionId的类型定义见下面:
 
typedef struct
{
    BackendId   backendId;      /* determined at backendstartup */
    LocalTransactionId localTransactionId;      /* backend-localtransaction
                                                 * id */
} VirtualTransactionId;
 
         然后为这个新事物调用下面的方法初始化相关子系统。
在事务开始时调用AtStart_GUC()设置事务嵌套层数,调用AtStart_Inval()方法初始化管理该事务失效信息用的TransInvalidationInfo类型结构,调用AtStart_Cache方法从共享失效消息队列读取并处理失效消息,调用AfterTriggerBeginXact方法初始化AfterTriggersData类型结构以备后面处理相关AFTER的触发器。AfterTriggersData的结构定义见下面:
         typedef struct AfterTriggersData
{
    CommandId   firing_counter; /* next firing ID to assign */
    SetConstraintState state;   /* the active S C state */
    AfterTriggerEventList events;       /* deferred-event list */
    int         query_depth;    /* current query list index */
    AfterTriggerEventList *query_stack; /* eventspending from each query */
    int         maxquerydepth;  /* allocated lenof abovearray */
    MemoryContext event_cxt;    /* memory context for events, if any */
 
    /* these fields are just for resetting at subtransabort: */
 
    SetConstraintState *state_stack;    /* stacked S C states */
    AfterTriggerEventList *events_stack;        /* stacked list pointers */
    int        *depth_stack; /* stacked query_depths */
    CommandId  *firing_stack;   /* stacked firing_counters */
    int         maxtransdepth;  /* allocated lenof abovearrays */
} AfterTriggersData;
 
在StartTransaction方法里主要干了上面这些事并设置了记录事务状态的结构CurrentTransactionState的成员,其中有一个成员TransState state,TransState是枚举类型,表示事务状态,其定义如下:
/*
 *  transactionstates - 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;
 
好了,这节就到这儿。
 
  

  

  ------------
转载请著明出处,来自博客:
blog.csdn.net/beiigang
beigang.iyunv.com


  

  
页: [1]
查看完整版本: PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询一:开启事务