文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PostgreSQL 源码解读(136)- Buffer Manager#1(ReadBufferExtended函数)

2024-04-02 19:55

关注

本节简单介绍了PostgreSQL缓存管理(Buffer Manager)中的其中一个实现函数ReadBufferExtended,该函数返回对应请求关系数据块的buffer.。

一、数据结构

Relation
关系的内存结构.




typedef struct RelationData
{
    RelFileNode rd_node;        
    
    struct SMgrRelationData *rd_smgr;   
    int         rd_refcnt;      
    BackendId   rd_backend;     
    bool        rd_islocaltemp; 
    bool        rd_isnailed;    
    bool        rd_isvalid;     
    char        rd_indexvalid;  
    bool        rd_statvalid;   
    
    SubTransactionId rd_createSubid;    
    SubTransactionId rd_newRelfilenodeSubid;    
    Form_pg_class rd_rel;       
    TupleDesc   rd_att;         
    Oid         rd_id;          
    LockInfoData rd_lockInfo;   
    RuleLock   *rd_rules;       
    MemoryContext rd_rulescxt;  
    TriggerDesc *trigdesc;      
    
    struct RowSecurityDesc *rd_rsdesc;  
    
    List       *rd_fkeylist;    
    bool        rd_fkeyvalid;   
    MemoryContext rd_partkeycxt;    
    struct PartitionKeyData *rd_partkey;    
    MemoryContext rd_pdcxt;     
    struct PartitionDescData *rd_partdesc;  
    List       *rd_partcheck;   
    
    List       *rd_indexlist;   
    Oid         rd_oidindex;    
    Oid         rd_pkindex;     
    Oid         rd_replidindex; 
    
    List       *rd_statlist;    
    
    Bitmapset  *rd_indexattr;   
    Bitmapset  *rd_projindexattr;   
    Bitmapset  *rd_keyattr;     
    Bitmapset  *rd_pkattr;      
    Bitmapset  *rd_idattr;      
    Bitmapset  *rd_projidx;     
    PublicationActions *rd_pubactions;  
    
    bytea      *rd_options;     
    
    Form_pg_index rd_index;     
    
    struct HeapTupleData *rd_indextuple;    
    
    Oid         rd_amhandler;   
    MemoryContext rd_indexcxt;  
    
    struct IndexAmRoutine *rd_amroutine;    
    Oid        *rd_opfamily;    
    Oid        *rd_opcintype;   
    RegProcedure *rd_support;   
    FmgrInfo   *rd_supportinfo; 
    int16      *rd_indoption;   
    List       *rd_indexprs;    
    List       *rd_indpred;     
    Oid        *rd_exclops;     
    Oid        *rd_exclprocs;   
    uint16     *rd_exclstrats;  
    void       *rd_amcache;     
    Oid        *rd_indcollation;    
    
    
    struct FdwRoutine *rd_fdwroutine;   
    
    Oid         rd_toastoid;    
    
    struct PgStat_TableStatus *pgstat_info; 
} RelationData;
typedef struct RelationData *Relation;

BufferAccessStrategy
buffer访问策略




typedef int Buffer;
#define InvalidBuffer   0

typedef struct BufferAccessStrategyData *BufferAccessStrategy;
 
typedef struct BufferAccessStrategyData
{
    
    //全局的策略类型
    BufferAccessStrategyType btype;
    
    //buffers[]中的元素个数
    int         ring_size;
    
    int         current;
    
    bool        current_was_in_ring;
    
    Buffer      buffers[FLEXIBLE_ARRAY_MEMBER];
}           BufferAccessStrategyData;
//Block结构体指针
typedef void *Block;

//GetAccessStrategy()函数可取值的参数
typedef enum BufferAccessStrategyType
{
    //常规的随机访问
    BAS_NORMAL,                 
    //大规模的只读扫描
    BAS_BULKREAD,               
    //大量的多块写(如 COPY IN)
    BAS_BULKWRITE,              
    //VACUUM
    BAS_VACUUM                  
} BufferAccessStrategyType;

ReadBufferMode
ReadBufferExtended函数所可能使用的读取模式.





typedef enum
{
    RBM_NORMAL,                 
    RBM_ZERO_AND_LOCK,          
    RBM_ZERO_AND_CLEANUP_LOCK,  
    RBM_ZERO_ON_ERROR,          
    RBM_NORMAL_NO_LOG           
} ReadBufferMode;

二、源码解读

ReadBufferExtended返回对应请求关系数据块的buffer,实现逻辑比较简单,详见代码.
主要的实现逻辑在ReadBuffer_common中,该函数后续再行介绍.




Buffer
ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
                   ReadBufferMode mode, BufferAccessStrategy strategy)
{
    bool        hit;
    Buffer      buf;
    
    //打开relation,级别为smgr
    RelationOpenSmgr(reln);
    
    if (RELATION_IS_OTHER_TEMP(reln))
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("cannot access temporary tables of other sessions")));
    
    pgstat_count_buffer_read(reln);
    buf = ReadBuffer_common(reln->rd_smgr, reln->rd_rel->relpersistence,
                            forkNum, blockNum, mode, strategy, &hit);
    if (hit)
        pgstat_count_buffer_hit(reln);
    return buf;
}

三、跟踪分析

使用bt查看调用栈



(gdb) bt
#0  ReadBufferExtended (reln=0x7f497fe72788, forkNum=MAIN_FORKNUM, blockNum=0, mode=RBM_NORMAL, strategy=0x0)
    at bufmgr.c:647
#1  0x00000000004d974f in heapgetpage (scan=0x1d969d8, page=0) at heapam.c:379
#2  0x00000000004daeb2 in heapgettup_pagemode (scan=0x1d969d8, dir=ForwardScanDirection, nkeys=0, key=0x0) at heapam.c:837
#3  0x00000000004dcf2b in heap_getnext (scan=0x1d969d8, direction=ForwardScanDirection) at heapam.c:1842
#4  0x000000000070ec39 in SeqNext (node=0x1d95890) at nodeSeqscan.c:80
#5  0x00000000006e0ab0 in ExecScanFetch (node=0x1d95890, accessMtd=0x70eba9 <SeqNext>, recheckMtd=0x70ec74 <SeqRecheck>)
    at execScan.c:95
#6  0x00000000006e0b22 in ExecScan (node=0x1d95890, accessMtd=0x70eba9 <SeqNext>, recheckMtd=0x70ec74 <SeqRecheck>)
    at execScan.c:145
#7  0x000000000070ecbe in ExecSeqScan (pstate=0x1d95890) at nodeSeqscan.c:129
#8  0x00000000006dee2a in ExecProcNodeFirst (node=0x1d95890) at execProcnode.c:445
#9  0x00000000007021b8 in ExecProcNode (node=0x1d95890) at ../../../src/include/executor/executor.h:237
#10 0x00000000007022dd in ExecLimit (pstate=0x1d95680) at nodeLimit.c:95
#11 0x00000000006dee2a in ExecProcNodeFirst (node=0x1d95680) at execProcnode.c:445
#12 0x00000000006d3d8d in ExecProcNode (node=0x1d95680) at ../../../src/include/executor/executor.h:237
#13 0x00000000006d65c5 in ExecutePlan (estate=0x1d95468, planstate=0x1d95680, use_parallel_mode=false, 
    operation=CMD_SELECT, sendTuples=true, numberTuples=0, direction=ForwardScanDirection, dest=0x1d00ea8, 
    execute_once=true) at execMain.c:1723
#14 0x00000000006d4357 in standard_ExecutorRun (queryDesc=0x1cfdc28, direction=ForwardScanDirection, count=0, 
    execute_once=true) at execMain.c:364
#15 0x00000000006d417f in ExecutorRun (queryDesc=0x1cfdc28, direction=ForwardScanDirection, count=0, execute_once=true)
    at execMain.c:307
#16 0x00000000008bffd4 in PortalRunSelect (portal=0x1d3ebf8, forward=true, count=0, dest=0x1d00ea8) at pquery.c:932
#17 0x00000000008bfc72 in PortalRun (portal=0x1d3ebf8, count=9223372036854775807, isTopLevel=true, run_once=true, 
    dest=0x1d00ea8, altdest=0x1d00ea8, completionTag=0x7ffc1fc513d0 "") at pquery.c:773
#18 0x00000000008b9cd4 in exec_simple_query (query_string=0x1cd8ec8 "select * from t1 limit 10;") at postgres.c:1145
---Type <return> to continue, or q <return> to quit---
#19 0x00000000008bdf5f in PostgresMain (argc=1, argv=0x1d05278, dbname=0x1d050e0 "testdb", username=0x1cd5ba8 "xdb")
    at postgres.c:4182
#20 0x000000000081c16d in BackendRun (port=0x1cfae00) at postmaster.c:4361
#21 0x000000000081b8e0 in BackendStartup (port=0x1cfae00) at postmaster.c:4033
#22 0x0000000000817cda in ServerLoop () at postmaster.c:1706
#23 0x0000000000817590 in PostmasterMain (argc=1, argv=0x1cd3b60) at postmaster.c:1379
#24 0x0000000000741003 in main (argc=1, argv=0x1cd3b60) at main.c:228
(gdb)

逻辑较为简单,这里不再详细跟踪.

四、参考资料

PG Source Code

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 资料下载
  • 历年真题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯