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

前端之家收集整理的这篇文章主要介绍了PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询一:开启事务前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

在《Postgresql服务过程中的那些事二:pg服务进程处理简单查询概览》里话说以下面的例子对简单查询分支进行讨论,并给出了简单查询方法调用序列,下面就从这儿开始,先回顾一下上节点内容

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



处理简单查询方法exec_simple_query调用序列图

主要的处理过程是先调用start_xact_command@H_403_21@方法开启一个事务,再用pg_parse_query@H_403_21@方法用词法语法解析工具把查询命令解析为解析树parsetree,根据需要调用PushActiveSnapshot@H_403_21@方法搞一个快照,调用pg_analyze_and_rewrite@H_403_21@方法分析、根据规则重写解析树为查询树querytree,调用pg_plan_queries@H_403_21@方法查询树转换到执行计划树plantree,在调用相应方法创建portal和在postal中执行执行计划树并给客户端发回结果。然后退出当前事务,清理内存。

1

现在描述这个例子:数据库TEST里有表TEST1、TEST2,现在客户端发出查询selectcname,comp from test1,test2 where test1.id=test2.id;@H_403_21@”。建表的语句在下面。

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方法后,使@H_301_103@TransactionStateData *类型静态全局变量CurrentTransactionState指向@H_301_103@TransactionStateData类型静态全局变量TopTransactionStateData,在CurrentTransactionState设置当前事务状态,记录当前事务ID和当前命令ID。然后调用AtStart_Memory方法创建内存上下文"TransactionAbortContext""TopTransactionContext",接着调用AtStart_ResourceOwner方法在内存上下文"TopMemoryContext"中创建资源属ResourceOwnerData类型变量curTransationOwner,并让CurrentTransactionStateResourceOwnerData*类型成员curTransactionOwner指向该变量。用以上建立的结构管理该事务涉及到资源。描述着比较难理清关系,看下面的图吧。



记录事务状态及管理事务资源的相关结构图

从图中看见事务相关的资源属主ResourceOwnerData管理的事务资源包括关系内存缓存、系统表缓存catcache、关系模式缓存relcache、执行计划缓存plancache查询命令相关元组描述符缓存tupdesc、事务相关快照以及打开的临时文件等。

事务状态及管理事务资源的相关结构见下面:

@H_502_201@/*

@H_502_201@* transactionstate structure

@H_502_201@*/

typedefstruct@H_403_21@ TransactionStateData

{

@H_301_103@TransactionIdtransactionId; @H_502_201@/* my XID,or Invalid if none */

@H_301_103@SubTransactionIdsubTransactionId; @H_502_201@/* my subxact ID */

char@H_403_21@ *name; @H_502_201@/* savepoint name,if any*/

int@H_403_21@ savepointLevel; @H_502_201@/* savepoint level */

@H_301_103@TransState state; @H_502_201@/* low-level state */

@H_301_103@TBlockStateblockState; @H_502_201@/* high-level state */

int@H_403_21@ nestingLevel; @H_502_201@/* transaction nesting depth */

int@H_403_21@ gucNestLevel; @H_502_201@/* GUC context nesting depth */

@H_301_103@MemoryContextcurTransactionContext; @H_502_201@/* my xact-lifetime context */

@H_301_103@ResourceOwnercurTransactionOwner; @H_502_201@/* my query resources */

@H_301_103@TransactionId *childXids; @H_502_201@/* subcommitted child XIDs,in XID order */

int@H_403_21@ nChildXids; @H_502_201@/* # of subcommitted childXIDs */

int@H_403_21@ maxChildXids; @H_502_201@/* allocated size of childXids[]*/

@H_301_103@Oid prevUser; @H_502_201@/* prevIoUs CurrentUserId setting*/

int@H_403_21@ prevSecContext; @H_502_201@/* prevIoUs SecurityRestrictionContext */

@H_301_103@bool prevXactReadOnly; @H_502_201@/* entry-time xact r/ostate */

@H_301_103@bool startedInRecovery; @H_502_201@/* did we start in recovery? */

struct@H_403_21@ TransactionStateData *parent; @H_502_201@/* back link to parent */

} @H_301_103@TransactionStateData;

typedef@H_403_21@@H_301_103@TransactionStateData *@H_301_103@TransactionState;

@H_502_201@/*

@H_502_201@* CurrentTransactionState always points to thecurrent transaction state

@H_502_201@* block.It will point to TopTransactionStateData when not in a

@H_502_201@* transaction at all,or when in a top-leveltransaction.

@H_502_201@*/

static@H_403_21@@H_301_103@TransactionStateData TopTransactionStateData = {

0,@H_502_201@/* transaction id */

0,@H_502_201@/* subtransaction id */

NULL,@H_502_201@/* savepoint name */

0,@H_502_201@/* savepoint level */

TRANS_DEFAULT,@H_502_201@/* transaction state */

TBLOCK_DEFAULT,@H_502_201@/* transaction block state fromthe client

@H_502_201@ * perspective */

0,@H_502_201@/* transaction nesting depth */

0,@H_502_201@/* GUC context nesting depth */

NULL,@H_502_201@/* cur transaction context */

NULL,@H_502_201@/* cur transaction resource owner*/

NULL,@H_502_201@/* subcommitted child Xids*/

0,@H_502_201@/* # of subcommitted child Xids*/

0,@H_502_201@/* allocated size of childXids[]*/

InvalidOid,@H_502_201@/* prevIoUs CurrentUserId setting*/

0,@H_502_201@/* prevIoUsSecurityRestrictionContext */

false,@H_502_201@/* entry-time xact r/ostate */

false,@H_502_201@/* startedInRecovery */

NULL @H_502_201@/* link to parent state block */

};

static@H_403_21@@H_301_103@TransactionState CurrentTransactionState =&TopTransactionStateData;

3

接着调用VirtualXactLockTableInsert方法给该事务一个VirtualTransactionId(这个类型是把pg服务进程ID和该进程上的事务ID关联起来的结构)类型的虚拟事务ID:VXID,并加锁。VirtualTransactionId的类型定义见下面:

typedefstruct@H_403_21@

{

@H_301_103@BackendId backendId; @H_502_201@/* determined at backendstartup */

@H_301_103@LocalTransactionIdlocalTransactionId; @H_502_201@/* backend-localtransaction

@H_502_201@ * id */

} VirtualTransactionId;

然后为这个新事物调用下面的方法初始化相关子系统。

在事务开始时调用AtStart_GUC()设置事务嵌套层数,调用AtStart_Inval()方法初始化管理该事务失效信息用的TransInvalidationInfo@H_301_103@类型结构,调用AtStart_Cache方法从共享失效消息队列读取并处理失效消息,调用AfterTriggerBeginXact方法初始化AfterTriggersData类型结构以备后面处理相关AFTER的触发器。AfterTriggersData的结构定义见下面:

typedefstruct@H_403_21@ AfterTriggersData

{

@H_301_103@CommandId firing_counter; @H_502_201@/* next firing ID to assign */

@H_301_103@SetConstraintStatestate; @H_502_201@/* the active S C state */

@H_301_103@AfterTriggerEventListevents; @H_502_201@/* deferred-event list */

int@H_403_21@ query_depth; @H_502_201@/* current query list index */

@H_301_103@AfterTriggerEventList *query_stack; @H_502_201@/* eventspending from each query */

int@H_403_21@ maxquerydepth; @H_502_201@/* allocated len of abovearray */

@H_301_103@MemoryContextevent_cxt; @H_502_201@/* memory context for events,if any */

@H_502_201@/* these fields are just for resetting at subtransabort: */

@H_301_103@SetConstraintState *state_stack; @H_502_201@/* stacked S C states */

@H_301_103@AfterTriggerEventList *events_stack; @H_502_201@/* stacked list pointers */

int@H_403_21@ *depth_stack; @H_502_201@/* stacked query_depths */

@H_301_103@CommandId *firing_stack; @H_502_201@/* stacked firing_counters */

int@H_403_21@ maxtransdepth; @H_502_201@/* allocated len of abovearrays */

} AfterTriggersData;

在StartTransaction方法里主要干了上面这些事并设置了记录事务状态的结构CurrentTransactionState的成员,其中有一个成员TransState stateTransState是枚举类型,表示事务状态,其定义如下:

@H_502_201@/*

@H_502_201@* transactionstates - transaction state from server perspective

@H_502_201@*/

typedefenum@H_403_21@ TransState

{

TRANS_DEFAULT,@H_502_201@/* idle */

TRANS_START,@H_502_201@/* transaction starting */

TRANS_INPROGRESS,@H_502_201@/* inside a valid transaction */

TRANS_COMMIT,@H_502_201@/* commit in progress */

TRANS_ABORT,@H_502_201@/* abort in progress */

TRANS_PREPARE @H_502_201@/* prepare in progress */

} @H_301_103@TransState;

好了,这节就到这儿。


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

猜你在找的Postgre SQL相关文章