BeiGang 发表于 2013-1-30 01:24:07

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
下面是做内存快照的调用序列图。

http://dl.iteye.com/upload/attachment/0075/1378/bea44fc7-145d-3ecd-9032-5e00cfbd74c1.png

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

http://dl.iteye.com/upload/attachment/0075/1380/59091e6f-fd9f-3f2a-8a65-a6fbf7ee1a10.png

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结构定义:
typedef struct SnapshotData
{
    SnapshotSatisfiesFunc satisfies;   /* 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.
     */
    TransactionId xmin;         /* all XID < xmin are visible to me */
    TransactionId xmax;         /* 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 < 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方法,其流程图在下面

http://dl.iteye.com/upload/attachment/0075/1382/18a2e978-d499-3cad-b211-ad8f52420935.png
 
RegisterSerializableTransactionInt流程图
 
RegisterSerializableTransactionInt里,利用predicatelock相关的哈西表,PredXactListData、PredXactListElementData等组成的链表结构,RWConflictPoolHeaderData、RWConflictData等组成的链表结构等一起管理predicate lock和serializablexact结构,(具体个数据结构参见《PostgreSQL启动过程中的那些事七:初始化共享内存和信号九:shmem中初始化Predicate锁》)利用可序列化快照隔离(Serializable SnapshotIsolation (SSI)),实现了事务的完全可序列化隔离级别,以支持该事务隔离级别下事务的正常运转。
 
              利用可序列化快照隔离(Serializable Snapshot Isolation (SSI))的相关情况最初是在下面的论文里描述:
    Michael J. Cahill, Uwe R枚hm, 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




        
页: [1]
查看完整版本: PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询三:获取内存快照