PostgreSQL Latch 实现逻辑

源码版本:pg 11.9

源码文件:src/backend/storage/ipc/latch.c


Latch 是 pg 中使用较多的一种数据结构,用于等待某个事件的发生或者超时,常见的 Latch 相关函数如下:


  • InitLatch(),初始化一个非共享型 Latch
  • InitSharedLatch(),初始化一个共享型 Latch
  • WaitLatch(),等待 Latch
  • ResetLatch(),重置 Latch
  • SetLatch(),设置 Latch 标记,唤醒等待 Latch 的进程
  • OwnLatch(),设置 Latch 的拥有者为当前进程
  • DisownLatch(),当前进程不再拥有该 Latch



Latch 结构体
typedef struct Latch
{
    sig_atomic_t is_set;
    bool is_shared;
    int owner_pid;
#ifdef WIN32
    HANDLE event;
#endif

} Latch;


共享型、独占型 Latch

Latch 可分为共享型和独占型,共享型 Latch 的 owner_pid 可变,即拥有该 Latch 的进程 pid 可变。


内部实现:
WaitLatch() 内部调用 WaitLatchOrSocket() 实现等待事件,可等待的事件类型包括 3 种:
  • Latch
  • Socket,socket 相关事件
  • Timeout,等待超时事件
关键的数据结构:
struct WaitEventSet;

struct WaitEvent;


一个 WaitEventSet 只能设置一个 Latch,可以设置多个 WaitEvent。通过函数 AddWaitEventToSet() 将 Latch、socket 等事件放置到 WaitEventSet 中。AddWaitEventToSet() 函数根据系统支持的多路复用模型epoll/poll/win32 不同类型,调用下面 3 个函数中的 1 个完成。
  • WaitEventAdjustEpoll()
  • WaitEventAdjustPoll()
  • WaitEventAdjustWin32()
调用函数 WaitEventSetWait() 等待事件的发生或者超时,内部调用 WaitEventSetWaitBlock() 函数,该函数根据 epoll/poll/win32 有不同的实现,最终调用的是如下 3 个函数中的 1 个。


  • epoll:epoll_wait()
  • poll:poll()
  • win32:WaitForMultipleObjects()



selfpipe管道
static int selfpipe_readfd = -1;

static int selfpipe_writefd = -1;


selfpipi 提供了 fd 用于监视,当 Latch 在等待过程中,进程可以接收信号,比如接收到 SIGUSR1 信号,通过函数 sendSelfPipeByte() 往 selfpipi 管道写入数据,唤醒等待 Latch 的进程。
SetLatch()函数的实现也是通过直接调用 sendSelfPipeByte() 往管道里写数据或者向指定进程发送 SIGUSR1 信号间接调用 sendSelfPipeByte() 来唤醒等待的进程。

文章评论

0条评论