设为首页 收藏本站
查看: 955|回复: 0

[经验分享] PostgreSQL启动过程中的那些事七:初始化共享内存和信号:四 shmem中初始化subtrans

[复制链接]

尚未签到

发表于 2016-11-21 07:48:48 | 显示全部楼层 |阅读模式
       pg初始化shmem,给其加上索引"ShmemIndex"后,接着就在shmem里初始化xlog。然后依次初始化clog、subtrans、twophase、multixact。安排按clog、subtrans、multixact、twophase的顺序写,把twophase放到multixact之后是因为前面三个用了相同的算法和数据结构,连起来写可以加深印象和归类记忆,本来想把初始化clog、subtrans、multixact放到一篇文章里写,因为篇幅太长还是分开了,看的时候这几篇文章可以结合起来看。
      

pg子事务管理器(pg_subtrans manager)是一个类提交事务管理器(pg_clog-like manager,关于clog见《pg启动过程中的那些事七-三》。),为每一个事务存储父事务ID。它是实现嵌套事务的一个基础部分。主事务有一个无效的父事务ID,且每个子事务以其为父事务。这颗事务树能方便的从子事务找到父事务,但不能从父事务找到子事务。子事务只需要为当前打开的事务记住子事务信息。这样没有必要像CLOG那样为进程崩溃或重启数据库保存数据。

因为不保存因崩溃恢复需要的数据,所以没有和XLOG的交互。在pg数据库启动期间,只要把子事务的当前活跃页置0就可以了。

上面概述了子事务,下来我们看方法调用流程

 
1先上个图,看一下函数调用过程梗概,中间略过部分细节
 
DSC0000.bmp
初始化SUBTRANS方法调用流程图

  
 

  
2初始化xlog相关结构
  
话说main()->…->PostmasterMain()->…->reset_shared()-> CreateSharedMemoryAndSemaphores()->…-> CLOGShmemInit(),初始化子事务相关数据结构ClogCtlData等,用作内存里管理和缓存子事务日志文件(存放在"data/pg_subtrans"文件夹里的文件)。
  
SUBTRANSShmemInit()调用ShmemInitStruct(),在其中调用hash_search()在哈希表索引"ShmemIndex"中查找"SUBTRANSCtl",如果没有,就在shmemIndex中给" SUBTRANS Ctl"分一个HashElement和ShmemIndexEntentry),在其中的Entry中写上"SUBTRANS Ctl"。返回ShmemInitStruct(),再调用ShmemAlloc()在共享内存上给"SUBTRANS Ctl"相关结构(见下面“subtrans相关结构图”)分配空间,设置entry(在这儿及ShmemIndexEnt类型变量)的成员location指向该空间,size成员记录该空间大小,最后返回SUBTRANSShmemInit(),让SlruCtlData *类型全局变量SubTransCtl指向SlruCtlData 类型静态全局变量SubTransCtlData,SubTransCtlData的起始地址就是在shmem里给" SUBTRANS Ctl"相关结构分配的内存起始地址,设置其中SubTransCtlData结构类型的成员值。相关变量、结构定义和初始化完成后数据结构图在下面。
  
 

  
#define SubTransCtl (&SubTransCtlData)

  
static SlruCtlData SubTransCtlData;

  
 

  
typedef structSlruCtlData

  
{

  
    SlruShared  shared;

  
 

  
    /*

  
     * This flag tells whether to fsync writes(true for pg_clog, false for

  
     * pg_subtrans).

  
     */

  
    bool        do_fsync;

  
 

  
    /*

  
     * Decide which of two page numbers is"older" for truncation purposes. We

  
     * need to use comparison of TransactionIdshere in order to do the right

  
     * thing with wraparound XID arithmetic.

  
     */

  
    bool        (*PagePrecedes)(int, int);

  
 

  
    /*

  
     * Dir is set during SimpleLruInit and does notchange thereafter. Since

  
     * it's always the same, it doesn't need to bein shared memory.

  
     */

  
    char        Dir[64];

  
} SlruCtlData;

  
 

  
typedef SlruCtlData *SlruCtl;

  
 

  
/*

  
 * Shared-memorystate

  
 */

  
typedef structSlruSharedData

  
{

  
    LWLockId    ControlLock;

  
 

  
    /* Number of buffers managed by this SLRU structure */

  
    int         num_slots;

  
 

  
    /*

  
     * Arrays holding info for each buffer slot.  Page number is undefined

  
     * when status is EMPTY, as is page_lru_count.

  
     */

  
    char      **page_buffer;

  
    SlruPageStatus*page_status;

  
    bool       *page_dirty;

  
    int        *page_number;

  
    int        *page_lru_count;

  
    LWLockId   *buffer_locks;

  
    /*

  
     * Optional array of WAL flush LSNs associatedwith entries in the SLRU

  
     * pages. If not zero/NULL, we must flush WAL before writing pages (true

  
     * for pg_clog, false for multixact,pg_subtrans, pg_notify).  group_lsn[]

  
     * has lsn_groups_per_page entries per bufferslot, each containing the

  
     * highest LSN known for a contiguous group ofSLRU entries on that slot's

  
     * page.

  
     */

  
    XLogRecPtr *group_lsn;

  
    int         lsn_groups_per_page;

  
    /*----------

  
     * We mark a page "most recentlyused" by setting

  
     *      page_lru_count[slotno]= ++cur_lru_count;

  
     * The oldest page is therefore the one withthe highest value of

  
     *      cur_lru_count- page_lru_count[slotno]

  
     * The counts will eventually wrap around, butthis calculation still

  
     * works as long as no page's age exceedsINT_MAX counts.

  
     *----------

  
*/

  
    int         cur_lru_count;

  
 

  
    /*

  
     * latest_page_number is the page number of thecurrent end of the log;

  
     * this is not critical data, since we use itonly to avoid swapping out

  
     * the latest page.

  
     */

  
    int         latest_page_number;

  
} SlruSharedData;

  
 

  
typedef SlruSharedData *SlruShared;

  
 

  
下面看看初始化完" SUBTRANS Ctl"相关结构后在内存中的结构图


DSC0001.bmp

 

初始化完SUBTRANS相关结构的内存结构图

  
       为了精简上图,把创建shmem的哈希表索引"ShmemIndex"时创建的HCTL结构删掉了,这个结构的作用是记录创建可扩展哈希表的相关信息。增加了左边灰色底的部分,描述共享内存/shmem里各变量物理布局概览,由下往上,由低地址到高地址。其中的"SUBTRANSCtl"即clog的相关结构图下面分别给出,要不上面的图太大太复杂了。

  
 

DSC0002.bmp

  
 

SUBTRANS相关结构图

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-303129-1-1.html 上篇帖子: PostgreSQL启动过程中的那些事七:初始化共享内存和信号三:shmem中初始化clog 下篇帖子: PostgreSQL启动过程中的那些事七:初始化共享内存和信号五:shmem中初始化multixact
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表