[作者:技术者高健@博客园  mail: luckyjackgao@gmail.com ]

在bgwriter的代码中,有这样一段,其中的MyProc显得很突兀:

/*                        * Loop forever                        */
for (;;)
{                        bool        can_hibernate;            int            rc;        /* Clear any already-pending wakeups */                    ResetLatch(&MyProc->procLatch);                    if (got_SIGHUP)                    {                    got_SIGHUP = false;                ProcessConfigFile(PGC_SIGHUP);                }                    if (shutdown_requested)                    {                    /*                * From here on, elog(ERROR) should end with exit(1), not send                * control back to the sigsetjmp block above                */                ExitOnAnyError = true;                /* Normal exit from the bgwriter is here */                proc_exit(0);        /* done */        }                    /*                    * Do one cycle of dirty-buffer writing.                    */                    can_hibernate = BgBufferSync();                    /*                    * Send off activity statistics to the stats collector                    */                    pgstat_send_bgwriter();                    if (FirstCallSinceLastCheckpoint())                    {                    /*                * After any checkpoint, close all smgr files.    This is so we            * won't hang onto smgr references to deleted files indefinitely.                */                smgrcloseall();                }                    /*                    * Sleep until we are signaled or BgWriterDelay has elapsed.                    *                    * Note: the feedback control loop in BgBufferSync() expects that we                    * will call it every BgWriterDelay msec.  While it's not critical for                    * correctness that that be exact, the feedback loop might misbehave                    * if we stray too far from that.  Hence, avoid loading this process                    * down with latch events that are likely to happen frequently during                    * normal operation.                    */                    rc = WaitLatch(&MyProc->procLatch,                    WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,        BgWriterDelay /* ms */ );        /*                    * If no latch event and BgBufferSync says nothing's happening, extend                    * the sleep in "hibernation" mode, where we sleep for much longer                    * than bgwriter_delay says.  Fewer wakeups save electricity.  When a                    * backend starts using buffers again, it will wake us up by setting                    * our latch.  Because the extra sleep will persist only as long as no                    * buffer allocations happen, this should not distort the behavior of                    * BgBufferSync's control loop too badly; essentially, it will think                    * that the system-wide idle interval didn't exist.                    *                    * There is a race condition here, in that a backend might allocate a                    * buffer between the time BgBufferSync saw the alloc count as zero                    * and the time we call StrategyNotifyBgWriter.  While it's not                    * critical that we not hibernate anyway, we try to reduce the odds of                    * that by only hibernating when BgBufferSync says nothing's happening                    * for two consecutive cycles.    Also, we mitigate any possible                * consequences of a missed wakeup by not hibernating forever.                    */                    if (rc == WL_TIMEOUT && can_hibernate && prev_hibernate)                    {                    /* Ask for notification at next buffer allocation */                StrategyNotifyBgWriter(&MyProc->procLatch);                /* Sleep ... */                rc = WaitLatch(&MyProc->procLatch,                WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,    BgWriterDelay * HIBERNATE_FACTOR);    /* Reset the notification request in case we timed out */                StrategyNotifyBgWriter(NULL);                }                    /*                    * Emergency bailout if postmaster has died.  This is to avoid the                    * necessity for manual cleanup of all postmaster children.                    */                    if (rc & WL_POSTMASTER_DEATH)                    exit(1);                prev_hibernate = can_hibernate;
}                        

MyProc究竟从哪里来呢?在proc.h中有说明:

/** Each backend has a PGPROC struct in shared memory.  There is also a list of* currently-unused PGPROC structs that will be reallocated to new backends.** links: list link for any list the PGPROC is in.    When waiting for a lock,* the PGPROC is linked into that lock's waitProcs queue.  A recycled PGPROC* is linked into ProcGlobal's freeProcs list.** Note: twophase.c also sets up a dummy PGPROC struct for each currently* prepared transaction.  These PGPROCs appear in the ProcArray data structure* so that the prepared transactions appear to be still running and are* correctly shown as holding locks.  A prepared transaction PGPROC can be* distinguished from a real one at need by the fact that it has pid == 0.* The semaphore and lock-activity fields in a prepared-xact PGPROC are unused,* but its myProcLocks[] lists are valid.*/
struct PGPROC
{/* proc->links MUST BE FIRST IN STRUCT (see ProcSleep,ProcWakeup,etc) */SHM_QUEUE    links;            /* list link if process is in a list */PGSemaphoreData sem;        /* ONE semaphore to sleep on */int            waitStatus;        /* STATUS_WAITING, STATUS_OK or STATUS_ERROR */Latch        procLatch;        /* generic latch for process */LocalTransactionId lxid;    /* local id of top-level transaction currently* being executed by this proc, if running;* else InvalidLocalTransactionId */int            pid;            /* Backend's process ID; 0 if prepared xact */int            pgprocno;/* These fields are zero while a backend is still starting up: */BackendId    backendId;        /* This backend's backend ID (if assigned) */Oid            databaseId;        /* OID of database this backend is using */Oid            roleId;            /* OID of role using this backend *//** While in hot standby mode, shows that a conflict signal has been sent* for the current transaction. Set/cleared while holding ProcArrayLock,* though not required. Accessed without lock, if needed.*/bool        recoveryConflictPending;/* Info about LWLock the process is currently waiting for, if any. */bool        lwWaiting;        /* true if waiting for an LW lock */uint8        lwWaitMode;        /* lwlock mode being waited for */struct PGPROC *lwWaitLink;    /* next waiter for same LW lock *//* Info about lock the process is currently waiting for, if any. *//* waitLock and waitProcLock are NULL if not currently waiting. */LOCK       *waitLock;        /* Lock object we're sleeping on ... */PROCLOCK   *waitProcLock;    /* Per-holder info for awaited lock */LOCKMODE    waitLockMode;    /* type of lock we're waiting for */LOCKMASK    heldLocks;        /* bitmask for lock types already held on this* lock object by this backend *//** Info to allow us to wait for synchronous replication, if needed.* waitLSN is InvalidXLogRecPtr if not waiting; set only by user backend.* syncRepState must not be touched except by owning process or WALSender.* syncRepLinks used only while holding SyncRepLock.*/XLogRecPtr    waitLSN;        /* waiting for this LSN or higher */int            syncRepState;    /* wait state for sync rep */SHM_QUEUE    syncRepLinks;    /* list link if process is in syncrep queue *//** All PROCLOCK objects for locks held or awaited by this backend are* linked into one of these lists, according to the partition number of* their lock.*/SHM_QUEUE    myProcLocks[NUM_LOCK_PARTITIONS];struct XidCache subxids;    /* cache for subtransaction XIDs *//* Per-backend LWLock.    Protects fields below. */LWLockId    backendLock;    /* protects the fields below *//* Lock manager data, recording fast-path locks taken by this backend. */uint64        fpLockBits;        /* lock modes held for each fast-path slot */Oid            fpRelId[FP_LOCK_SLOTS_PER_BACKEND];        /* slots for rel oids */bool        fpVXIDLock;        /* are we holding a fast-path VXID lock? */LocalTransactionId fpLocalTransactionId;    /* lxid for fast-path VXID* lock */
};/* NOTE: "typedef struct PGPROC PGPROC" appears in storage/lock.h. */extern PGDLLIMPORT PGPROC *MyProc;
extern PGDLLIMPORT struct PGXACT *MyPgXact;

其中有一段说的:

/*
* Each backend has a PGPROC struct in shared memory. There is also a list of
* currently-unused PGPROC structs that will be reallocated to new backends.
*

也就是说,bgwriter 也好,wal writer 也罢,都有一个 类似的结构在内存中,而各个后台进程,就是靠着这个内存结构进行着一些通信。

再看这个

rc = WaitLatch(&MyProc->procLatch,                    WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,        BgWriterDelay /* ms */ );  看unix 平台上的 unix_latch.c 代码:
/** Wait for a given latch to be set, or for postmaster death, or until timeout* is exceeded. 'wakeEvents' is a bitmask that specifies which of those events* to wait for. If the latch is already set (and WL_LATCH_SET is given), the* function returns immediately.** The 'timeout' is given in milliseconds. It must be >= 0 if WL_TIMEOUT flag* is given.  On some platforms, signals do not interrupt the wait, or even* cause the timeout to be restarted, so beware that the function can sleep* for several times longer than the requested timeout.  However, this* difficulty is not so great as it seems, because the signal handlers for any* signals that the caller should respond to ought to be programmed to end the* wait by calling SetLatch.  Ideally, the timeout parameter is vestigial.** The latch must be owned by the current process, ie. it must be a* backend-local latch initialized with InitLatch, or a shared latch* associated with the current process by calling OwnLatch.** Returns bit mask indicating which condition(s) caused the wake-up. Note* that if multiple wake-up conditions are true, there is no guarantee that* we return all of them in one call, but we will return at least one.*/
int
WaitLatch(volatile Latch *latch, int wakeEvents, long timeout)
{return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout);
}

第一个参数就是 latch了,这个是必须的。第二个就是 事件,第三个是超时参数。

[作者:技术者高健@博客园  mail: luckyjackgao@gmail.com ]

结束

对PostgreSQL中bgwriter的 MyProc 的理解相关推荐

  1. PostgreSQL中的io多路复用--select和epoll实现

    某天和同事闲聊,同事发现一个现象,PostgreSQL在空闲状态时(没有active连接),主进程的pstack显示一直在调用/lib64/libc.so.6的__select_nocancel () ...

  2. PostgreSQL 中的引号与大小写

    单双引号 单引号用来标识实际的值,双引号用来标识表名(table name)或列名(column name)等数据库中存在的值. select "name" from " ...

  3. postgresql 插入 时间戳_数据也玩躲猫猫?PostgreSQL中别人提交的数据,我为什么看不到?...

    原创: Aken DB印象 文章链接:https://mp.weixin.qq.com/s/OkJaWbzcXcJtzSCOFnqeXQ 文章作为DB的学习体会,若有错误欢迎指导. 一.环境介绍 操作 ...

  4. Postgresql杂谈 04—Postgresql中的五种常规索引

    一.索引的分类 Postgresql中索引一共分为5种,每一种都有它合适的应用场景,我们在使用时要根据不同业务的特点,选择合适的索引,这样才能加快sql语句的查询效率.下面,我们将就每种不同的索引,介 ...

  5. Postgresql杂谈 20—详解Postgresql中的Checkpoint、WAL日志和热备份恢复

    本文中,我们共同学习下Postgresql的WAL日志.WAL,是Write Ahead Log的简称,翻译过来就是预写日志,或者叫做重做日志.相信大家对数据库事务的四大特性ACID(原子性.一致性. ...

  6. Postgresql中的large object

    1.初识postgresql large object 一位同事在对使用pg_dump备份出来的文件(使用plain格式)进行恢复时,觉得速度非常慢,让我分析一下是什么原因. 我拿到他的.bak文件, ...

  7. PostgreSQL中的查询:1.查询执行阶段

    PostgreSQL中的查询:1.查询执行阶段 开始关于PG内部执行机制的文章系列.这一篇侧重于查询计划和执行机制. 本系列包括: 1.查询执行阶段(本文) 2.统计数据 3.顺序扫描 4.索引扫描 ...

  8. PostgreSQL中的索引—6(SP-GiST)

    目录 SP-GiST 架构 示例:四叉树 内部构件 示例:k维树 内部构件 示例:基数树 内部构件 属性 NULL 其他数据类型 我们已经介绍了Postgresql索引引擎.访问方法接口和三种方法:哈 ...

  9. pg数据库json数据类型_科学网—如何使用PostgreSQL中的JSONB数据类型(PG JSON系列2) - 孙鹏的博文...

    上一篇 使用PostgreSQL中的row_to_json()直接获得JSON(PG JSON系列1)主要针对现有的非json/jsonb类型如何输出json结果,这一篇主要写一下在数据库设计中直接使 ...

最新文章

  1. mysql启动后在哪里编程_启动mysql后怎么连接数据库
  2. 从粗放到精细,如何用AI技术实现信息流广告投放的降本增效
  3. Python元组与字典详解
  4. zigbee抗干扰matlab仿真,基于Zigbee的扩频通信MATLAB仿真.doc
  5. UI5 xml view里control id的生成逻辑
  6. PWN-PRACTICE-BUUCTF-8
  7. 这是一个非常不错的mkv编辑制作的软件!
  8. react-native 第三方库
  9. 如何不获取root权限使用第三方主题:MIUI篇
  10. excel表转成PDF文档
  11. vscode 设置关键字高亮显示
  12. 第三章 集合的基本概念和运算
  13. 【Qt】仿QQ表情选择控件
  14. 【SpringBoot】SpringBoot的banner制作
  15. 基于Docker的frp内网穿透
  16. 【GTASA】如何解锁Locked的DFF模型
  17. 苹果CMS海螺模版V4.0修复版
  18. PyQt5 QtChart-曲线图
  19. ALtera DE2开发板学习
  20. 《java编程思想》第七章 复用类

热门文章

  1. [RMAN]表空间的恢复
  2. Hbase高级功能过滤(Filter)
  3. 深度解析 | K8S API Server之请求处理
  4. 各型号交换机端口镜像配置方法和命令
  5. 2016年度太和顾问北京高科技行业人力资本数据信息发布
  6. U盘安装linux后无法引导
  7. 新生赛3 1003 字符串最小表示法题目
  8. jave se基础复习2
  9. 643. 子数组最大平均数 I
  10. 【免费毕设】ASP.NET猜数游戏的设计与开发(源代码+lunwen)