PostgreSQL Latch 实现逻辑

2023年 8月 15日 29.2k 0

源码版本: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() 来唤醒等待的进程。

相关文章

在一台虚拟机上搭建MGR 9.0集群
众所周知的原因安装PMM2
唯一上榜!OceanBase入选 2023“科创中国”先导技术榜!
MySQL 删除数据表
利用 MySQL 克隆插件搭建主从
MySQL索引前缀长度超限怎么办?这种方法帮你搞定

发布评论