返回顶部
首页 > 资讯 > 数据库 >PostgreSQL 源码解读(136)- Buffer Manager#1(ReadBufferExtended函数)
  • 128
分享到

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

2024-04-02 19:04:59 128人浏览 薄情痞子
摘要

本节简单介绍了postgresq

本节简单介绍了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

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL 源码解读(136)- Buffer Manager#1(ReadBufferExtended函数)

本文链接: https://lsjlt.com/news/48532.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作