跳转到主要内容

I/O 等待

文件读取、写入、同步、分配与异步 I/O 完成。

IO 表示 PostgreSQL 已为某个文件操作设置探针,而后端必须等内核或另一个 I/O worker 推进后才能继续。它指出的是哪条 PostgreSQL 文件路径,但单凭事件本身不能证明存储很慢。

把事件、操作和负载阶段一起读

名称通常同时编码对象与操作:DataFileReadWalSyncSlruWriteReorderBufferRead。先问当前负载是否本来就该执行这项操作,再把持续时间与并发度关联到 pg_stat_io(PG16+)和操作系统延迟。

  • 正常: 扫描读取数据文件,检查点同步脏文件,备份读写,恢复读取 WAL。
  • 关注: 同一个前台 I/O 事件在连续样本中存在,而且设备或查询延迟上升。
  • 紧急: 大量后端排队等待 sync/write、出现错误,或受影响路径达到饱和/限速。

值得先认出的事件

事件 第一解释
DataFileRead 缓存未命中或扫描正在读取关系数据
DataFileWrite 后端/检查点路径正在写关系数据
DataFileSync 关系改动正在持久化
WalWrite 正在写入 WAL 字节
WalSync WAL 持久性边界等待 fsync/fdatasync
SlruRead 读取事务相关 SLRU 页面
BuffileRead 读取临时/溢写文件
AioIoCompletion PG18 AIO 工作尚未完成

PG16+ I/O 上下文

SELECT backend_type, object, context,
       reads, read_time, writes, write_time,
       writebacks, fsyncs, fsync_time
FROM pg_stat_io
ORDER BY coalesce(read_time, 0) + coalesce(write_time, 0) + coalesce(fsync_time, 0) DESC;

常见误读

  • 有意执行顺序扫描时,大量 DataFileRead 可能只是健康吞吐。
  • WalWrite 与 LWLock WALWrite 不是一回事:前者是文件操作,后者是内部协调。
  • 设备平均延迟可能掩盖单块 WAL 卷饱和或长尾延迟尖刺。
  • 增大缓存不能解决所有读取等待;糟糕计划和一次性冷扫描仍可能挤出有用页面。

等待基础备份写入的数据到达持久化存储。

等待在文件复制操作期间读取数据。

等待 relation 数据文件到达持久化存储。

等待从 relation 数据文件中读取数据。

等待 relation 数据文件的变更到达持久化存储。

等待创建数据目录锁文件时写入的数据到达持久化存储。

等待检查点或数据库关闭期间的 SLRU 数据到达持久化存储。

等待页面写入后的 SLRU 数据到达持久化存储。

等待读取序列化的历史系统目录 snapshot。

等待序列化的历史系统目录 snapshot 到达持久化存储。

等待写入序列化的历史系统目录 snapshot。

等待创建数据库时的版本文件到达持久化存储。

等待通过复制现有 WAL segment 创建新 WAL segment 时读取数据。

等待通过复制现有 WAL segment 创建的新 WAL segment 到达持久化存储。

等待通过复制现有 WAL segment 创建新 WAL segment 时写入数据。

等待新初始化的 WAL 文件到达持久化存储。

等待在初始化新 WAL 文件时写入数据。

等待从 WAL 文件中读取数据。

等待 WAL 文件到达持久化存储。

等待分配新的 WAL 同步方法时写入的数据到达持久化存储。

等待向 WAL 文件写入数据。