iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL中mdread函数有什么作用
  • 848
分享到

PostgreSQL中mdread函数有什么作用

2024-04-02 19:04:59 848人浏览 安东尼
摘要

本篇内容主要讲解“postgresql中mdread函数有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Postgresql中mdread函数有什么作用

本篇内容主要讲解“postgresql中mdread函数有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Postgresql中mdread函数有什么作用”吧!

PostgreSQL存储管理的mdread函数是magnetic disk存储管理中负责读取的函数.

一、数据结构

smgrsw
f_smgr函数指针结构体定义了独立的存储管理模块和smgr.c之间的api函数.
md是magnetic disk的缩写.
除了md,先前PG还支持Sony WORM optical disk jukebox and persistent main memory这两种存储方式,
但在后面只剩下magnetic disk,其余的已被废弃不再支持.
“magnetic disk”本身的名称也存在误导,实际上md可以支持操作系统提供标准文件系统的任何类型的设备.

 
typedef struct f_smgr
{
    void        (*smgr_init) (void);    
    void        (*smgr_shutdown) (void);    
    void        (*smgr_close) (SMgrRelation reln, ForkNumber forknum);
    void        (*smgr_create) (SMgrRelation reln, ForkNumber forknum,
                                bool isRedo);
    bool        (*smgr_exists) (SMgrRelation reln, ForkNumber forknum);
    void        (*smgr_unlink) (RelFilenodeBackend rnode, ForkNumber forknum,
                                bool isRedo);
    void        (*smgr_extend) (SMgrRelation reln, ForkNumber forknum,
                                BlockNumber blocknum, char *buffer, bool skipFsync);
    void        (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum,
                                  BlockNumber blocknum);
    void        (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
                              BlockNumber blocknum, char *buffer);
    void        (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
                               BlockNumber blocknum, char *buffer, bool skipFsync);
    void        (*smgr_writeback) (SMgrRelation reln, ForkNumber forknum,
                                   BlockNumber blocknum, BlockNumber nblocks);
    BlockNumber (*smgr_nblocks) (SMgrRelation reln, ForkNumber forknum);
    void        (*smgr_truncate) (SMgrRelation reln, ForkNumber forknum,
                                  BlockNumber nblocks);
    void        (*smgr_immedsync) (SMgrRelation reln, ForkNumber forknum);
    void        (*smgr_pre_ckpt) (void);    
    void        (*smgr_sync) (void);    
    void        (*smgr_post_ckpt) (void);   
} f_smgr;

static const f_smgr smgrsw[] = {
    
    {
        .smgr_init = mdinit,
        .smgr_shutdown = NULL,
        .smgr_close = mdclose,
        .smgr_create = mdcreate,
        .smgr_exists = mdexists,
        .smgr_unlink = mdunlink,
        .smgr_extend = mdextend,
        .smgr_prefetch = mdprefetch,
        .smgr_read = mdread,
        .smgr_write = mdwrite,
        .smgr_writeback = mdwriteback,
        .smgr_nblocks = mdnblocks,
        .smgr_truncate = mdtruncate,
        .smgr_immedsync = mdimmedsync,
        .smgr_pre_ckpt = mdpreckpt,
        .smgr_sync = mdsync,
        .smgr_post_ckpt = mdpostckpt
    }
};

MdfdVec
magnetic disk存储管理在自己的描述符池中跟踪打开的文件描述符.
之所以这样做是因为便于支持超过os文件大小上限(通常是2GB)的关系.
为了达到这个目的,我们拆分关系为多个比OS文件大小上限要小的”segment”文件.
段大小通过pg_config.h中定义的RELSEG_SIZE配置参数设置.


typedef struct _MdfdVec
{
    //文件描述符池中该文件的编号
    File        mdfd_vfd;       
    //段号,从0起算
    BlockNumber mdfd_segno;     
} MdfdVec;

二、源码解读

mdread() — 从relation中读取相应的block.
源码较为简单,主要是调用FileRead函数执行实际的读取操作.


void
mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
       char *buffer)
{
    off_t       seekpos;//seek的位置
    int         nbytes;//bytes
    MdfdVec    *v;//md文件描述符向量数组
    TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum,
                                        reln->smgr_rnode.node.spcNode,
                                        reln->smgr_rnode.node.dbNode,
                                        reln->smgr_rnode.node.relNode,
                                        reln->smgr_rnode.backend);
    //获取向量数组
    v = _mdfd_getseg(reln, forknum, blocknum, false,
                     EXTENSION_FAIL | EXTENSION_CREATE_RECOVERY);
    //获取block偏移
    seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
    //验证
    Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
    //读取文件,读入buffer中,返回读取的字节数
    nbytes = FileRead(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_READ);
    //跟踪
    TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum,
                                       reln->smgr_rnode.node.spcNode,
                                       reln->smgr_rnode.node.dbNode,
                                       reln->smgr_rnode.node.relNode,
                                       reln->smgr_rnode.backend,
                                       nbytes,
                                       BLCKSZ);
    if (nbytes != BLCKSZ)
    {
        //读取的字节数不等于块大小,报错
        if (nbytes < 0)
            ereport(ERROR,
                    (errcode_for_file_access(),
                     errmsg("could not read block %u in file \"%s\": %m",
                            blocknum, FilePathName(v->mdfd_vfd))));
        
        if (zero_damaged_pages || InRecovery)
            MemSet(buffer, 0, BLCKSZ);
        else
            ereport(ERROR,
                    (errcode(ERRCODE_DATA_CORRUPTED),
                     errmsg("could not read block %u in file \"%s\": read only %d of %d bytes",
                            blocknum, FilePathName(v->mdfd_vfd),
                            nbytes, BLCKSZ)));
    }
}

三、跟踪分析

测试脚本

11:15:11 (xdb@[local]:5432)testdb=# insert into t1(id) select generate_series(100,500);

启动gdb,跟踪
查看调用栈

(gdb) b mdread
Breakpoint 3 at 0x8b669b: file md.c, line 738.
(gdb) c
Continuing.
Breakpoint 3, mdread (reln=0x2d09be0, forknum=MAIN_FORKNUM, blocknum=50, buffer=0x7f3823369c00 "") at md.c:738
738     TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum,
(gdb) bt
#0  mdread (reln=0x2d09be0, forknum=MAIN_FORKNUM, blocknum=50, buffer=0x7f3823369c00 "") at md.c:738
#1  0x00000000008b92d5 in smgrread (reln=0x2d09be0, forknum=MAIN_FORKNUM, blocknum=50, buffer=0x7f3823369c00 "")
    at smgr.c:628
#2  0x00000000008793f9 in ReadBuffer_common (smgr=0x2d09be0, relpersistence=112 'p', forkNum=MAIN_FORKNUM, blockNum=50, 
    mode=RBM_NORMAL, strategy=0x0, hit=0x7ffd5fb2948b) at bufmgr.c:890
#3  0x0000000000878cd4 in ReadBufferExtended (reln=0x7f3836e1e788, forkNum=MAIN_FORKNUM, blockNum=50, mode=RBM_NORMAL, 
    strategy=0x0) at bufmgr.c:664
#4  0x0000000000878bb1 in ReadBuffer (reln=0x7f3836e1e788, blockNum=50) at bufmgr.c:596
#5  0x00000000004eeb96 in ReadBufferBI (relation=0x7f3836e1e788, targetBlock=50, bistate=0x0) at hio.c:87
#6  0x00000000004ef387 in RelationGetBufferForTuple (relation=0x7f3836e1e788, len=32, otherBuffer=0, options=0, 
    bistate=0x0, vmbuffer=0x7ffd5fb295ec, vmbuffer_other=0x0) at hio.c:415
#7  0x00000000004df1f8 in heap_insert (relation=0x7f3836e1e788, tup=0x2ca6770, cid=0, options=0, bistate=0x0)
    at heapam.c:2468
#8  0x0000000000709dda in ExecInsert (mtstate=0x2ca4c40, slot=0x2ca3418, planSlot=0x2ca3418, estate=0x2ca48d8, 
    canSetTag=true) at nodeModifyTable.c:529
#9  0x000000000070c475 in ExecModifyTable (pstate=0x2ca4c40) at nodeModifyTable.c:2159
#10 0x00000000006e05cb in ExecProcNodeFirst (node=0x2ca4c40) at execProcnode.c:445
#11 0x00000000006d552e in ExecProcNode (node=0x2ca4c40) at ../../../src/include/executor/executor.h:247
#12 0x00000000006d7d66 in ExecutePlan (estate=0x2ca48d8, planstate=0x2ca4c40, use_parallel_mode=false, 
    operation=CMD_INSERT, sendTuples=false, numberTuples=0, direction=ForwardScanDirection, dest=0x2d41a30, 
    execute_once=true) at execMain.c:1723
#13 0x00000000006d5af8 in standard_ExecutorRun (queryDesc=0x2ca24b8, direction=ForwardScanDirection, count=0, 
    execute_once=true) at execMain.c:364
#14 0x00000000006d5920 in ExecutorRun (queryDesc=0x2ca24b8, direction=ForwardScanDirection, count=0, execute_once=true)
    at execMain.c:307
#15 0x00000000008c1092 in ProcessQuery (plan=0x2d418b8, 
    sourceText=0x2c7eec8 "insert into t1(id) select generate_series(100,500);", params=0x0, queryEnv=0x0, dest=0x2d41a30, 
---Type <return> to continue, or q <return> to quit---
    completionTag=0x7ffd5fb29b80 "") at pquery.c:161
#16 0x00000000008c29a1 in PortalRunMulti (portal=0x2ce4488, isTopLevel=true, setHoldSnapshot=false, dest=0x2d41a30, 
    altdest=0x2d41a30, completionTag=0x7ffd5fb29b80 "") at pquery.c:1286
#17 0x00000000008c1f7a in PortalRun (portal=0x2ce4488, count=9223372036854775807, isTopLevel=true, run_once=true, 
    dest=0x2d41a30, altdest=0x2d41a30, completionTag=0x7ffd5fb29b80 "") at pquery.c:799
#18 0x00000000008bbf16 in exec_simple_query (query_string=0x2c7eec8 "insert into t1(id) select generate_series(100,500);")
    at postgres.c:1145
#19 0x00000000008c01a1 in PostgresMain (arGC=1, argv=0x2ca8af8, dbname=0x2ca8960 "testdb", username=0x2c7bba8 "xdb")
    at postgres.c:4182
#20 0x000000000081e07c in BackendRun (port=0x2ca0940) at postmaster.c:4361
#21 0x000000000081d7ef in BackendStartup (port=0x2ca0940) at postmaster.c:4033
#22 0x0000000000819be9 in ServerLoop () at postmaster.c:1706
#23 0x000000000081949f in PostmasterMain (argc=1, argv=0x2c79b60) at postmaster.c:1379
#24 0x0000000000742941 in main (argc=1, argv=0x2c79b60) at main.c:228
(gdb)

获取读取的偏移

(gdb) n
744     v = _mdfd_getseg(reln, forknum, blocknum, false,
(gdb) 
747     seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
(gdb) p *v
$1 = {mdfd_vfd = 26, mdfd_segno = 0}
(gdb) p BLCKSZ
$2 = 8192
(gdb) p blocknum
$3 = 50
(gdb) p RELSEG_SIZE
$4 = 131072
(gdb) n
749     Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
(gdb) p seekpos
$5 = 409600
(gdb)

执行读取操作

(gdb) n
751     if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)
(gdb) 
757     nbytes = FileRead(v->mdfd_vfd, buffer, BLCKSZ, WAIT_EVENT_DATA_FILE_READ);
(gdb) 
759     TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum,
(gdb) p nbytes
$6 = 8192
(gdb) p *buffer
$7 = 1 '\001'
(gdb) n
767     if (nbytes != BLCKSZ)
(gdb) 
792 }
(gdb) 
smgrread (reln=0x2d09be0, forknum=MAIN_FORKNUM, blocknum=50, buffer=0x7f3823369c00 "\001") at smgr.c:629
629 }
(gdb)

到此,相信大家对“PostgreSQL中mdread函数有什么作用”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL中mdread函数有什么作用

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

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

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PostgreSQL中mdread函数有什么作用
    本篇内容主要讲解“PostgreSQL中mdread函数有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中mdread函数有什么作用...
    99+
    2024-04-02
  • PostgreSQL中hash_search_with_hash_value函数有什么作用
    本篇内容主要讲解“PostgreSQL中hash_search_with_hash_value函数有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Pos...
    99+
    2024-04-02
  • PostgreSQL中set_base_rel_pathlists函数有什么作用
    这篇文章主要介绍“PostgreSQL中set_base_rel_pathlists函数有什么作用”,在日常操作中,相信很多人在PostgreSQL中set_base_rel_pathlists函数有什么作...
    99+
    2024-04-02
  • PostgreSQL中grouping_planner函数有什么作用
    这篇文章主要介绍“PostgreSQL中grouping_planner函数有什么作用”,在日常操作中,相信很多人在PostgreSQL中grouping_planner函数有什么作用问题上存在疑惑,小编查...
    99+
    2024-04-02
  • PostgreSQL中BufferAlloc函数有什么作用
    这篇文章主要介绍“PostgreSQL中BufferAlloc函数有什么作用”,在日常操作中,相信很多人在PostgreSQL中BufferAlloc函数有什么作用问题上存在疑惑,小编查阅了各式资料,整理出...
    99+
    2024-04-02
  • PostgreSQL中fsm_search函数有什么作用
    本篇内容介绍了“PostgreSQL中fsm_search函数有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能...
    99+
    2024-04-02
  • PostgreSQL中StrategyGetBuffer函数有什么作用
    本篇内容介绍了“PostgreSQL中StrategyGetBuffer函数有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大...
    99+
    2024-04-02
  • PostgreSQL中heap_insert函数有什么作用
    这篇文章主要讲解了“PostgreSQL中heap_insert函数有什么作用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL中heap_...
    99+
    2024-04-02
  • PostgreSQL中create_index_path函数有什么作用
    本篇内容主要讲解“PostgreSQL中create_index_path函数有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中cr...
    99+
    2024-04-02
  • PostgreSQL中RelationGetBufferForTuple函数有什么作用
    这篇文章主要讲解了“PostgreSQL中RelationGetBufferForTuple函数有什么作用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Po...
    99+
    2024-04-02
  • PostgreSQL中BufTableInsert函数有什么作用
    本篇内容介绍了“PostgreSQL中BufTableInsert函数有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细...
    99+
    2024-04-02
  • PostgreSQL中ReadBuffer_common函数有什么作用
    这篇文章主要介绍“PostgreSQL中ReadBuffer_common函数有什么作用”,在日常操作中,相信很多人在PostgreSQL中ReadBuffer_common函数有什么作用问题上存在疑惑,小...
    99+
    2024-04-02
  • PostgreSQL中fetch_upper_rel和get_cheapest_fractional_path函数有什么作用
    这篇文章主要介绍“PostgreSQL中fetch_upper_rel和get_cheapest_fractional_path函数有什么作用”,在日常操作中,相信很多人在PostgreSQL中fetch_...
    99+
    2024-04-02
  • PostgreSQL的dump函数有什么作用
    本篇内容主要讲解“PostgreSQL的dump函数有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL的dump函数有什么作用”吧!O...
    99+
    2024-04-02
  • PostgreSQL的vacuum过程中lazy_vacuum_heap函数有什么作用
    这篇文章主要介绍“PostgreSQL的vacuum过程中lazy_vacuum_heap函数有什么作用”,在日常操作中,相信很多人在PostgreSQL的vacuum过程中lazy_vacuum_heap...
    99+
    2024-04-02
  • PostgreSQL中函数pg_blocking_pids的作用是什么
    本篇内容介绍了“PostgreSQL中函数pg_blocking_pids的作用是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大...
    99+
    2024-04-02
  • PostgreSQL中​ExecutePlan函数与ExecSeqScan函数的作用是什么
    这篇文章主要介绍“PostgreSQL中ExecutePlan函数与ExecSeqScan函数的作用是什么”,在日常操作中,相信很多人在PostgreSQL中ExecutePlan函数与ExecSeqSca...
    99+
    2024-04-02
  • PostgreSQL中pgbench有什么作用
    本篇内容主要讲解“PostgreSQL中pgbench有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中pgbench有什么作用”吧...
    99+
    2024-04-02
  • PostgreSQL中ReceiveXlogStream有什么作用
    这篇文章主要介绍“PostgreSQL中ReceiveXlogStream有什么作用”,在日常操作中,相信很多人在PostgreSQL中ReceiveXlogStream有什么作用问题上存在疑惑,小编查阅了...
    99+
    2024-04-02
  • PostgreSQL中RecordAndGetPageWithFreeSpace有什么作用
    本篇内容介绍了“PostgreSQL中RecordAndGetPageWithFreeSpace有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作