PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询三:获取内存快照

话说查询“selectcname, comp from test1, test2 where test1.id=test2.id;发送到服务器端,走查询分支exec_simple_query,先调用start_xact_command初始化了事务管理相关对象和资源,接着调用pg_parse_query,通过Lex和Yacc对传入SQL语句进行词法语法解析,生成解析树。下来调用GetTransactionSnapshot方法做内存快照。内存快照和事务隔离级别紧密相关,其中可重复读和序列化隔离级别每个数据库事务使用一个快照,读未提交和读已提交隔离级别每个语句使用一个快照。序列化隔离级别除快照外还使用predicate锁。

1

下面是做内存快照的调用序列图。



Postgres服务进程简查之开始事务调用序列图

上图红色方框中显示了获取内存快照的方法调用过程,在GetSnapshotData方法中根据事务隔离级别等情况获取相应快照,一般可优化语句(增、删、查、改)都需要快照,然后注册相应快照。下面是获取快照方法GetTransactionSnapshot的流程图。



GetTransactionSnapshot方法流程图

GetTransactionSnapshot()方法根据事务隔离级别 分别处理取快照的情况。如果事务隔离级别是读未提交、读已提交,调用GetSnapshotData(&CurrentSnapshotData)方法获取一个快照赋给CurrentSnapshot,返回CurrentSnapshot。如果事务隔离级别是可重复读或序列化,且是事务里第一次获取快照,直接返回CurrentSnapshot;不是第一次且是可重复读 事务隔离级别,调用GetSnapshotData(&CurrentSnapshotData) 方法获取一个快照赋给CurrentSnapshot,然后调用RegisterSnapshotOnOwner(CurrentSnapshot, TopTransactionResourceOwner)方法在资源管理器TopTransactionResourceOwner里注册这个快照;不是第一次且是序列化 事务隔离级别,调用RegisterSerializableTransaction(&CurrentSnapshotData)方法,根据需要调用GetSnapshotData方法获取快照并调用RegisterSnapshotOnOwner方法在资源属主TopTransactionResourceOwner上注册快照,并初始化一个可序列化事务SERIALIZABLEXACT结构和哈西表。最后,不管什么情况都返回当前快照,调用PushActiveSnapshot方法,把这个快照推入由ActiveSnapshotElt构成的“活跃快照”栈。

pg里快照就是数据结构SnapshotData,定义如下,表示某个时刻内存里对象的状态,下面是快照SnapshotData结构定义:

typedefstruct SnapshotData

{

SnapshotSatisfiesFuncsatisfies; /* tuple test function */

/*

* The remaining fields areused only for MVCC snapshots, and are normally

* just zeroes in specialsnapshots. (But xmin and xmaxare used

* specially byHeapTupleSatisfiesDirty.)

*

* An MVCC snapshot cannever see the effects of XIDs >= xmax. It can see

* the effects of all older XIDs except thoselisted in the snapshot.

xmin

* is stored as anoptimization to avoid needing to search the XID arrays

* for most tuples.

*/

TransactionIdxmin; /* all XID < xmin are visible to me */

TransactionIdxmax; /* all XID >= xmax are invisible to me */

uint32 xcnt; /* # of xact ids in xip[] */

TransactionId *xip; /* array of xact IDs in progress */

/* 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? */

/*

* 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 onRegisteredSnapshotList */

bool copied; /* false if it's a static snapshot */

} SnapshotData;

这里面最复杂的是在序列化隔离级别下事务的正常运转,部分体现在RegisterSerializableTransaction方法调用了RegisterSerializableTransactionInt方法,其流程图在下面



RegisterSerializableTransactionInt流程图


RegisterSerializableTransactionInt里,利用predicatelock相关的哈西表,PredXactListDataPredXactListElementData等组成的链表结构,RWConflictPoolHeaderDataRWConflictData等组成的链表结构等一起管理predicate lockserializablexact结构,(具体个数据结构参见PostgreSQL启动过程中的那些事七:初始化共享内存和信号九:shmem中初始化Predicate锁》)利用可序列化快照隔离(Serializable SnapshotIsolation (SSI),实现了事务的完全可序列化隔离级别,以支持该事务隔离级别下事务的正常运转。

利用可序列化快照隔离(Serializable Snapshot Isolation (SSI))的相关情况最初是在下面的论文里描述:

Michael J. Cahill, Uwe Rhm, and Alan D. Fekete. 2008.

Serializableisolation for snapshot databases.

InSIGMOD '08: Proceedings of the 2008 ACM SIGMOD

internationalconference on Management of data,

pages729-738, New York, NY, USA. ACM.

http://doi.acm.org/10.1145/1376616.1376690

在下面的博士论文里做了进一步阐述。

Michael James Cahill. 2009.

Serializable Isolation for Snapshot Databases.

Sydney Digital Theses.

University of Sydney, School of Information Technologies.

http://hdl.handle.net/2123/5353

就到这儿吧。

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值