PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询一:开启事务
2012-09-25 20:00
549 查看
在《PostgreSQL服务过程中的那些事二:pg服务进程处理简单查询概览》里话说以下面的例子对简单查询分支进行讨论,并给出了简单查询方法调用序列,下面就从这儿开始,先回顾一下上节点内容。
进入简单查询分支处理方法exec_simple_query后的处理基本上涵盖了《数据库系统实现》这本书里的内容。处理量相当大,先根据流程图概览一下处理过程。为了减小图的大小,把PostgresMain以前的调用流程略了。在以后讨论简单查询时PostgresMain以前的调用流程也省略了,要回顾可参见《PostgreSQL服务过程中的那些事二:pg服务进程处理简单查询概览》里的“Postgres服务进程处理请求的无限循环调用序列图”。
![](http://dl.iteye.com/upload/attachment/0074/3354/68a3fcaa-e942-375e-9f54-844d8f48a1bd.png)
处理简单查询方法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方法的简化流程图
![](http://dl.iteye.com/upload/attachment/0074/3356/41bed933-8f89-3e55-9257-7fbc7a119e44.png)
exec_simple_query方法的简化流程图
2
进了excu_simple_query分支的第一件事就是开启一个事务命令,pg里所有查询都要在事务里进行。下面是开启事务的调用序列图。
![](http://dl.iteye.com/upload/attachment/0074/3358/a85891c8-9bff-3896-a1f6-8601e1625123.png)
Postgres服务进程简查之开始事务调用序列图
上图大红色方框中显示了启动事物的相关的相关处理,进入StartTransaction方法后,使TransactionStateData *类型静态全局变量CurrentTransactionState指向TransactionStateData类型静态全局变量TopTransactionStateData,在CurrentTransactionState设置当前事务状态,记录当前事务ID和当前命令ID。然后调用AtStart_Memory方法创建内存上下文"TransactionAbortContext"和"TopTransactionContext",接着调用AtStart_ResourceOwner方法在内存上下文"TopMemoryContext"中创建资源属主ResourceOwnerData类型变量curTransationOwner,并让CurrentTransactionState的ResourceOwnerData*类型成员curTransactionOwner指向该变量。用以上建立的结构管理该事务涉及到资源。描述着比较难理清关系,看下面的图吧。
![](http://dl.iteye.com/upload/attachment/0074/3360/b3498d8a-c8ff-3d39-92d6-ed8fc81b0ba2.png)
记录事务状态及管理事务资源的相关结构图
从图中看见事务相关的资源属主ResourceOwnerData管理的事务资源包括关系内存缓存、系统表缓存catcache、关系模式缓存relcache、执行计划缓存plancache、查询命令相关元组描述符缓存tupdesc、事务相关快照以及打开的临时文件等。
事务状态及管理事务资源的相关结构见下面:
/*
* transactionstate structure
*/
typedefstruct TransactionStateData
{
TransactionIdtransactionId;
/* my XID, or Invalid if none */
SubTransactionIdsubTransactionId;
/* my subxact ID */
char
*name;
/* savepoint name, if any*/
int
savepointLevel;
/* savepoint level */
TransState
state;
/* low-level state */
TBlockStateblockState;
/* high-level state */
int
nestingLevel;
/* transaction nesting depth */
int
gucNestLevel;
/* GUC context nesting depth */
MemoryContextcurTransactionContext;
/* my xact-lifetime context */
ResourceOwnercurTransactionOwner;
/* my query resources */
TransactionId *childXids;
/* subcommitted child XIDs, in XID order */
int
nChildXids;
/* # of subcommitted childXIDs */
int
maxChildXids;
/* allocated size of childXids[]*/
Oid
prevUser;
/* previous CurrentUserId setting*/
int
prevSecContext;
/* previous SecurityRestrictionContext */
bool
prevXactReadOnly;
/* entry-time xact r/ostate */
bool
startedInRecovery;
/* did we start in recovery? */
struct TransactionStateData *parent;
/* back link to parent */
} TransactionStateData;
typedefTransactionStateData *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.
*/
staticTransactionStateData
TopTransactionStateData = {
0,
/* transaction id */
0,
/* subtransaction id */
NULL,
/* savepoint name */
0,
/* savepoint level */
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,
/* subcommitted child
Xids*/
0,
/* # of subcommitted child
Xids*/
0,
/* allocated size of childXids[]*/
InvalidOid,
/* previous CurrentUserId setting*/
0,
/* previousSecurityRestrictionContext */
false,
/* entry-time xact r/ostate */
false,
/* startedInRecovery */
NULL
/* link to parent state block */
};
staticTransactionState
CurrentTransactionState =&TopTransactionStateData;
3
接着调用VirtualXactLockTableInsert方法给该事务一个VirtualTransactionId(这个类型是把pg服务进程ID和该进程上的事务ID关联起来的结构)类型的虚拟事务ID:VXID,并加锁。VirtualTransactionId的类型定义见下面:
typedefstruct
{
BackendId
backendId;
/* determined at backendstartup */
LocalTransactionIdlocalTransactionId;
/* backend-localtransaction
* id */
} VirtualTransactionId;
然后为这个新事物调用下面的方法初始化相关子系统。
在事务开始时调用AtStart_GUC()设置事务嵌套层数,调用AtStart_Inval()方法初始化管理该事务失效信息用的TransInvalidationInfo类型结构,调用AtStart_Cache方法从共享失效消息队列读取并处理失效消息,调用AfterTriggerBeginXact方法初始化AfterTriggersData类型结构以备后面处理相关AFTER的触发器。AfterTriggersData的结构定义见下面:
typedefstruct AfterTriggersData
{
CommandId
firing_counter;
/* next firing ID to assign */
SetConstraintStatestate;
/* the active S C state */
AfterTriggerEventListevents;
/* deferred-event list */
int
query_depth;
/* current query list index */
AfterTriggerEventList *query_stack;
/* eventspending from each query */
int
maxquerydepth;
/* allocated len of abovearray */
MemoryContextevent_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 len of abovearrays */
} AfterTriggersData;
在StartTransaction方法里主要干了上面这些事并设置了记录事务状态的结构CurrentTransactionState的成员,其中有一个成员TransState
state,TransState是枚举类型,表示事务状态,其定义如下:
/*
* transactionstates - transaction state from server perspective
*/
typedefenum 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.iteye.com
进入简单查询分支处理方法exec_simple_query后的处理基本上涵盖了《数据库系统实现》这本书里的内容。处理量相当大,先根据流程图概览一下处理过程。为了减小图的大小,把PostgresMain以前的调用流程略了。在以后讨论简单查询时PostgresMain以前的调用流程也省略了,要回顾可参见《PostgreSQL服务过程中的那些事二:pg服务进程处理简单查询概览》里的“Postgres服务进程处理请求的无限循环调用序列图”。
![](http://dl.iteye.com/upload/attachment/0074/3354/68a3fcaa-e942-375e-9f54-844d8f48a1bd.png)
处理简单查询方法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方法的简化流程图
![](http://dl.iteye.com/upload/attachment/0074/3356/41bed933-8f89-3e55-9257-7fbc7a119e44.png)
exec_simple_query方法的简化流程图
2
进了excu_simple_query分支的第一件事就是开启一个事务命令,pg里所有查询都要在事务里进行。下面是开启事务的调用序列图。
![](http://dl.iteye.com/upload/attachment/0074/3358/a85891c8-9bff-3896-a1f6-8601e1625123.png)
Postgres服务进程简查之开始事务调用序列图
上图大红色方框中显示了启动事物的相关的相关处理,进入StartTransaction方法后,使TransactionStateData *类型静态全局变量CurrentTransactionState指向TransactionStateData类型静态全局变量TopTransactionStateData,在CurrentTransactionState设置当前事务状态,记录当前事务ID和当前命令ID。然后调用AtStart_Memory方法创建内存上下文"TransactionAbortContext"和"TopTransactionContext",接着调用AtStart_ResourceOwner方法在内存上下文"TopMemoryContext"中创建资源属主ResourceOwnerData类型变量curTransationOwner,并让CurrentTransactionState的ResourceOwnerData*类型成员curTransactionOwner指向该变量。用以上建立的结构管理该事务涉及到资源。描述着比较难理清关系,看下面的图吧。
![](http://dl.iteye.com/upload/attachment/0074/3360/b3498d8a-c8ff-3d39-92d6-ed8fc81b0ba2.png)
记录事务状态及管理事务资源的相关结构图
从图中看见事务相关的资源属主ResourceOwnerData管理的事务资源包括关系内存缓存、系统表缓存catcache、关系模式缓存relcache、执行计划缓存plancache、查询命令相关元组描述符缓存tupdesc、事务相关快照以及打开的临时文件等。
事务状态及管理事务资源的相关结构见下面:
/*
* transactionstate structure
*/
typedefstruct TransactionStateData
{
TransactionIdtransactionId;
/* my XID, or Invalid if none */
SubTransactionIdsubTransactionId;
/* my subxact ID */
char
*name;
/* savepoint name, if any*/
int
savepointLevel;
/* savepoint level */
TransState
state;
/* low-level state */
TBlockStateblockState;
/* high-level state */
int
nestingLevel;
/* transaction nesting depth */
int
gucNestLevel;
/* GUC context nesting depth */
MemoryContextcurTransactionContext;
/* my xact-lifetime context */
ResourceOwnercurTransactionOwner;
/* my query resources */
TransactionId *childXids;
/* subcommitted child XIDs, in XID order */
int
nChildXids;
/* # of subcommitted childXIDs */
int
maxChildXids;
/* allocated size of childXids[]*/
Oid
prevUser;
/* previous CurrentUserId setting*/
int
prevSecContext;
/* previous SecurityRestrictionContext */
bool
prevXactReadOnly;
/* entry-time xact r/ostate */
bool
startedInRecovery;
/* did we start in recovery? */
struct TransactionStateData *parent;
/* back link to parent */
} TransactionStateData;
typedefTransactionStateData *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.
*/
staticTransactionStateData
TopTransactionStateData = {
0,
/* transaction id */
0,
/* subtransaction id */
NULL,
/* savepoint name */
0,
/* savepoint level */
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,
/* subcommitted child
Xids*/
0,
/* # of subcommitted child
Xids*/
0,
/* allocated size of childXids[]*/
InvalidOid,
/* previous CurrentUserId setting*/
0,
/* previousSecurityRestrictionContext */
false,
/* entry-time xact r/ostate */
false,
/* startedInRecovery */
NULL
/* link to parent state block */
};
staticTransactionState
CurrentTransactionState =&TopTransactionStateData;
3
接着调用VirtualXactLockTableInsert方法给该事务一个VirtualTransactionId(这个类型是把pg服务进程ID和该进程上的事务ID关联起来的结构)类型的虚拟事务ID:VXID,并加锁。VirtualTransactionId的类型定义见下面:
typedefstruct
{
BackendId
backendId;
/* determined at backendstartup */
LocalTransactionIdlocalTransactionId;
/* backend-localtransaction
* id */
} VirtualTransactionId;
然后为这个新事物调用下面的方法初始化相关子系统。
在事务开始时调用AtStart_GUC()设置事务嵌套层数,调用AtStart_Inval()方法初始化管理该事务失效信息用的TransInvalidationInfo类型结构,调用AtStart_Cache方法从共享失效消息队列读取并处理失效消息,调用AfterTriggerBeginXact方法初始化AfterTriggersData类型结构以备后面处理相关AFTER的触发器。AfterTriggersData的结构定义见下面:
typedefstruct AfterTriggersData
{
CommandId
firing_counter;
/* next firing ID to assign */
SetConstraintStatestate;
/* the active S C state */
AfterTriggerEventListevents;
/* deferred-event list */
int
query_depth;
/* current query list index */
AfterTriggerEventList *query_stack;
/* eventspending from each query */
int
maxquerydepth;
/* allocated len of abovearray */
MemoryContextevent_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 len of abovearrays */
} AfterTriggersData;
在StartTransaction方法里主要干了上面这些事并设置了记录事务状态的结构CurrentTransactionState的成员,其中有一个成员TransState
state,TransState是枚举类型,表示事务状态,其定义如下:
/*
* transactionstates - transaction state from server perspective
*/
typedefenum 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.iteye.com
相关文章推荐
- PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询五:规划成plantree
- PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询二:SQL解析为parsetree
- PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询三:获取内存快照
- PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询四:分析重写成querytree
- PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询六:执行器执行
- 转载:PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询六:执行器执行
- PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询梗概
- PostgreSQL服务过程中的那些事三:pg服务进程中的内存上下文
- PostgreSQL启动过程中的那些事十三_十四:初始化统计进程需要的资源、为autovuc进程启动做条件检查
- Mybatis实例 简单查询 事务处理 关联、集合查询 鉴别器 动态SQL及各种标签实例
- SQLServer-存储过程中的简单事务处理
- PostgreSQL启动过程中的那些事十八:bgwriter进程二
- PostgreSQL服务过程中的那些事一:启动postgres服务进程一.八:加载DB基础设施,完成服务进程初始化
- 关于存储过程中一个参数表示多个查询条件使用方法的简单处理
- PostgreSQL启动过程中的那些事十二.五:启动系统日志进程syslogger
- 存储过程中的简单事务处理---SQLServer2005系列
- PostgreSQL启动过程中的那些事十八:bgwriter进程一
- MySQL第五天---存储过程、查询区分大小写、事务(MySQL及Java实现的简单模板)
- PostgreSQL服务过程中的那些事一:启动postgres服务进程一.五:初始化relcache管理环境
- PostgreSQL:pgloader导入导出处理重复数据简单示例