广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL checkpoint中用于刷一个脏page的函数是什么
  • 247
分享到

PostgreSQL checkpoint中用于刷一个脏page的函数是什么

2024-04-02 19:04:59 247人浏览 独家记忆
摘要

这篇文章主要讲解了“postgresql checkpoint中用于刷一个脏page的函数是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Postgre

这篇文章主要讲解了“postgresql checkpoint中用于刷一个脏page的函数是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Postgresql checkpoint中用于刷一个脏page的函数是什么”吧!

一、数据结构

宏定义
checkpoints request flag bits,检查点请求标记位定义.



#define CHECKPOINT_IS_SHUTDOWN  0x0001  
#define CHECKPOINT_END_OF_RECOVERY  0x0002  
#define CHECKPOINT_IMMEDIATE  0x0004  
#define CHECKPOINT_FORCE    0x0008  
#define CHECKPOINT_FLUSH_ALL  0x0010  

#define CHECKPOINT_WaiT     0x0020  
#define CHECKPOINT_REQUESTED  0x0040  

#define CHECKPOINT_CAUSE_XLOG 0x0080  
#define CHECKPOINT_CAUSE_TIME 0x0100  

二、源码解读

SyncOneBuffer,在syncing期间处理一个buffer,其主要处理逻辑如下:
1.获取buffer描述符
2.定buffer
3.根据buffer状态和输入参数执行相关判断/处理
4.钉住脏页,上共享锁,调用FlushBuffer刷盘
5.解锁/解钉和其他收尾工作


static int
SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
{
  BufferDesc *bufHdr = GetBufferDescriptor(buf_id);
  int     result = 0;
  uint32    buf_state;
  BufferTag tag;
  ReservePrivateRefCountEntry();
  
  buf_state = LockBufHdr(bufHdr);
  if (BUF_STATE_GET_REFCOUNT(buf_state) == 0 &&
    BUF_STATE_GET_USAGECOUNT(buf_state) == 0)
  {
    result |= BUF_REUSABLE;
  }
  else if (skip_recently_used)
  {
    
    //跳过最近使用的buffer
    UnlockBufHdr(bufHdr, buf_state);
    return result;
  }
  if (!(buf_state & BM_VALID) || !(buf_state & BM_DIRTY))
  {
    
    //buffer无效或者不是脏块
    UnlockBufHdr(bufHdr, buf_state);
    return result;
  }
  
  PinBuffer_Locked(bufHdr);
  LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED);
  //调用FlushBuffer
  //If the caller has an smgr reference for the buffer's relation, pass it as the second parameter.  
  //If not, pass NULL.
  FlushBuffer(bufHdr, NULL);
  LWLockRelease(BufferDescriptorGetContentLock(bufHdr));
  tag = bufHdr->tag;
  UnpinBuffer(bufHdr, true);
  ScheduleBufferTagForWriteback(wb_context, &tag);
  return result | BUF_WRITTEN;
}

FlushBuffer
FlushBuffer函数物理上把共享缓存刷盘,主要实现函数还是smgrwrite(storage manager write).


static void
FlushBuffer(BufferDesc *buf, SMgrRelation reln)
{
  XLogRecPtr  recptr;
  ErrorContextCallback errcallback;
  instr_time  io_start,
        io_time;
  Block   bufBlock;
  char     *bufToWrite;
  uint32    buf_state;
  
  if (!StartBufferIO(buf, false))
    return;
  
  errcallback.callback = shared_buffer_write_error_callback;
  errcallback.arg = (void *) buf;
  errcallback.previous = error_context_stack;
  error_context_stack = &errcallback;
  
  if (reln == NULL)
    reln = smgropen(buf->tag.rnode, InvalidBackendId);
  TRACE_POSTGRESQL_BUFFER_FLUSH_START(buf->tag.forkNum,
                    buf->tag.blockNum,
                    reln->smgr_rnode.node.spcNode,
                    reln->smgr_rnode.node.dbNode,
                    reln->smgr_rnode.node.relNode);
  buf_state = LockBufHdr(buf);
  
  recptr = BufferGetLSN(buf);
  
  buf_state &= ~BM_JUST_DIRTIED;
  UnlockBufHdr(buf, buf_state);
  
  if (buf_state & BM_PERMANENT)
    XLogFlush(recptr);
  
  bufBlock = BufHdrGetBlock(buf);
  
  bufToWrite = PageSetChecksumCopy((Page) bufBlock, buf->tag.blockNum);
  if (track_io_timing)
    INSTR_TIME_SET_CURRENT(io_start);
  
  smgrwrite(reln,
        buf->tag.forkNum,
        buf->tag.blockNum,
        bufToWrite,
        false);
  if (track_io_timing)
  {
    INSTR_TIME_SET_CURRENT(io_time);
    INSTR_TIME_SUBTRACT(io_time, io_start);
    pgstat_count_buffer_write_time(INSTR_TIME_GET_MICROSEC(io_time));
    INSTR_TIME_ADD(pgBufferUsage.blk_write_time, io_time);
  }
  pgBufferUsage.shared_blks_written++;
  
  TerminateBufferIO(buf, true, 0);
  TRACE_POSTGRESQL_BUFFER_FLUSH_DONE(buf->tag.forkNum,
                     buf->tag.blockNum,
                     reln->smgr_rnode.node.spcNode,
                     reln->smgr_rnode.node.dbNode,
                     reln->smgr_rnode.node.relNode);
  
  error_context_stack = errcallback.previous;
}

三、跟踪分析

测试脚本

testdb=# update t_wal_ckpt set c2 = 'C4#'||substr(c2,4,40);
UPDATE 1
testdb=# checkpoint;

跟踪分析

(gdb) handle SIGINT print nostop pass
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) y
Signal        Stop  Print Pass to program Description
SIGINT        No  Yes Yes   Interrupt
(gdb) b SyncOneBuffer
Breakpoint 1 at 0x8a7167: file bufmgr.c, line 2357.
(gdb) c
Continuing.
Program received signal SIGINT, Interrupt.
Breakpoint 1, SyncOneBuffer (buf_id=0, skip_recently_used=false, wb_context=0x7fff27f5ae00) at bufmgr.c:2357
2357    BufferDesc *bufHdr = GetBufferDescriptor(buf_id);
(gdb) n
2358    int     result = 0;
(gdb) p *bufHdr
$1 = {tag = {rnode = {spcNode = 1663, dbNode = 16384, relNode = 221290}, forkNum = MAIN_FORKNUM, blockNum = 0}, buf_id = 0, 
  state = {value = 3548905472}, wait_backend_pid = 0, freeNext = -2, content_lock = {tranche = 53, state = {
      value = 536870912}, waiters = {head = 2147483647, tail = 2147483647}}}
(gdb) n
2362    ReservePrivateRefCountEntry();
(gdb) 
2373    buf_state = LockBufHdr(bufHdr);
(gdb) 
2375    if (BUF_STATE_GET_REFCOUNT(buf_state) == 0 &&
(gdb) 
2376      BUF_STATE_GET_USAGECOUNT(buf_state) == 0)
(gdb) 
2375    if (BUF_STATE_GET_REFCOUNT(buf_state) == 0 &&
(gdb) 
2380    else if (skip_recently_used)
(gdb) 
2387    if (!(buf_state & BM_VALID) || !(buf_state & BM_DIRTY))
(gdb) 
2398    PinBuffer_Locked(bufHdr);
(gdb) p buf_state
$2 = 3553099776
(gdb) n
2399    LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED);
(gdb) 
2401    FlushBuffer(bufHdr, NULL);
(gdb) step
FlushBuffer (buf=0x7fedc4a68300, reln=0x0) at bufmgr.c:2687
2687    if (!StartBufferIO(buf, false))
(gdb) n
2691    errcallback.callback = shared_buffer_write_error_callback;
(gdb) 
2692    errcallback.arg = (void *) buf;
(gdb) 
2693    errcallback.previous = error_context_stack;
(gdb) 
2694    error_context_stack = &errcallback;
(gdb) 
2697    if (reln == NULL)
(gdb) 
2698      reln = smgropen(buf->tag.rnode, InvalidBackendId);
(gdb) 
2700    TRACE_POSTGRESQL_BUFFER_FLUSH_START(buf->tag.forkNum,
(gdb) 
2706    buf_state = LockBufHdr(buf);
(gdb) 
2712    recptr = BufferGetLSN(buf);
(gdb) 
2715    buf_state &= ~BM_JUST_DIRTIED;
(gdb) p recptr
$3 = 16953421760
(gdb) n
2716    UnlockBufHdr(buf, buf_state);
(gdb) 
2735    if (buf_state & BM_PERMANENT)
(gdb) 
2736      XLogFlush(recptr);
(gdb) 
2743    bufBlock = BufHdrGetBlock(buf);
(gdb) 
2750    bufToWrite = PageSetChecksumCopy((Page) bufBlock, buf->tag.blockNum);
(gdb) p bufBlock
$4 = (Block) 0x7fedc4e68300
(gdb) n
2752    if (track_io_timing)
(gdb) 
2758    smgrwrite(reln,
(gdb) 
2764    if (track_io_timing)
(gdb) 
2772    pgBufferUsage.shared_blks_written++;
(gdb) 
2778    TerminateBufferIO(buf, true, 0);
(gdb) 
2780    TRACE_POSTGRESQL_BUFFER_FLUSH_DONE(buf->tag.forkNum,
(gdb) 
2787    error_context_stack = errcallback.previous;
(gdb) 
2788  }
(gdb) 
SyncOneBuffer (buf_id=0, skip_recently_used=false, wb_context=0x7fff27f5ae00) at bufmgr.c:2403
2403    LWLockRelease(BufferDescriptorGetContentLock(bufHdr));
(gdb) 
2405    tag = bufHdr->tag;
(gdb) 
2407    UnpinBuffer(bufHdr, true);
(gdb) 
2409    ScheduleBufferTagForWriteback(wb_context, &tag);
(gdb) 
2411    return result | BUF_WRITTEN;
(gdb) 
2412  }
(gdb)

感谢各位的阅读,以上就是“PostgreSQL checkpoint中用于刷一个脏page的函数是什么”的内容了,经过本文的学习后,相信大家对PostgreSQL checkpoint中用于刷一个脏page的函数是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL checkpoint中用于刷一个脏page的函数是什么

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

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

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

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

下载Word文档
猜你喜欢
  • PostgreSQL checkpoint中用于刷一个脏page的函数是什么
    这篇文章主要讲解了“PostgreSQL checkpoint中用于刷一个脏page的函数是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Postgre...
    99+
    2022-10-18
  • checkpoint中用于控制刷盘频率的函数是什么
    这篇文章主要介绍“checkpoint中用于控制刷盘频率的函数是什么”,在日常操作中,相信很多人在checkpoint中用于控制刷盘频率的函数是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方...
    99+
    2022-10-18
  • PostgreSQL中函数pg_blocking_pids的作用是什么
    本篇内容介绍了“PostgreSQL中函数pg_blocking_pids的作用是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大...
    99+
    2022-10-18
  • PostgreSQL ExecAgg中调用的函数是什么
    本篇内容主要讲解“PostgreSQL ExecAgg中调用的函数是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL ExecAgg中调用...
    99+
    2022-10-18
  • PostgreSQL中​ExecutePlan函数与ExecSeqScan函数的作用是什么
    这篇文章主要介绍“PostgreSQL中ExecutePlan函数与ExecSeqScan函数的作用是什么”,在日常操作中,相信很多人在PostgreSQL中ExecutePlan函数与ExecSeqSca...
    99+
    2022-10-18
  • Python函数中参数前面一个和两个星号的区别是什么
    这篇文章主要讲解了“Python函数中参数前面一个和两个星号的区别是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python函数中参数前面一个和两个星号的区别是什么”吧!在 Pytho...
    99+
    2023-06-01
  • Python中的五个超有用函数是什么
    这篇文章主要介绍“Python中的五个超有用函数是什么”,在日常操作中,相信很多人在Python中的五个超有用函数是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python中的五个超有用函数是什么”的疑...
    99+
    2023-06-22
  • Python中itertools库的四个函数是什么及怎么用
    这篇文章主要介绍了Python中itertools库的四个函数是什么及怎么用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Python中itertools库的四个函数是什么及怎么用文章都会有所收获,下面我们一起...
    99+
    2023-06-29
  • 计算机中一个c程序的执行是从什么函数开始
    小编给大家分享一下计算机中一个c程序的执行是从什么函数开始,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一个c程序的执行是从本程序的main函数开始,到main函...
    99+
    2023-06-14
  • Pandas中常用的七个时间戳处理函数是什么
    这篇文章主要介绍“Pandas中常用的七个时间戳处理函数是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Pandas中常用的七个时间戳处理函数是什么”文章能帮助大家解决问题。在零售、经济和金融等...
    99+
    2023-06-30
  • 为什么在 MySQL 中使用两位数年份的日期值不是一个好习惯?
    众所周知,YEAR(2) 以 2 位数字格式存储年份。例如,我们可以写 69 将 1969 存储为年份。在 YEAR (2) 中,年份可以指定为 1970 到 2069(70 到 69)。MySQL 借助以下规则解释 2 位年份值 -00-...
    99+
    2023-10-22
  • 什么是Go中对象和函数的最佳实践,以及如何将它们应用于框架开发?
    Go语言是一种高效、简洁、可靠的编程语言,被广泛应用于云计算、网络编程、分布式系统等领域。在Go语言中,对象和函数是编写高质量代码的重要组成部分。本文将介绍Go中对象和函数的最佳实践,并讨论如何将它们应用于框架开发。 一、对象的最佳实践 在...
    99+
    2023-11-03
    对象 函数 框架
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作