bigywater.tech
PostgreSQL · 14

PostgreSQL synchronous_commit 和 fsync 对吞吐的影响:pgbench 实测,fsync_writethrough 只有 276 tps,批量提交 37595 行/秒对逐行提交 9168 行/秒

“PostgreSQL 的 synchronous_commit 和 fsync 到底影响多大、批量提交能快多少” 经常被泛泛而谈。这篇在本机自己起一个 PostgreSQL 16.15,用 pg_test_fsync 和 pgbench 量各种刷盘方式、同步提交开关、并发连接数(组提交)和批量提交的吞吐,同时如实指出这台 Mac 的默认刷盘方式与真实磁盘的差别。

342.777 对 20849.947
pg_test_fsync 里 fsync_writethrough 与默认 open_datasync 每秒能做的次数
3778 → 12609 tps
默认设置下 pgbench 从 1 个连接到 16 个连接的吞吐(组提交)
9168 → 37595 行/秒
逐行提交与每 100 行提交一次的插入速度

刷盘方式

实测 · 本机执行输出
  show wal_sync_method = open_datasync ;show fsync = on ;show synchronous_commit = on
      Compare file sync methods using one 8kB write:
      open_datasync 20849.947 ops/sec 48 usecs/op
      fdatasync 41813.198 ops/sec 24 usecs/op
      fsync 42542.792 ops/sec 24 usecs/op
      fsync_writethrough 342.777 ops/sec 2917 usecs/op
      open_sync 20951.961 ops/sec 48 usecs/op

各种 wal_sync_method 速度差两个数量级,fsync_writethrough 最慢。

组提交

实测 · 本机执行输出
       连接数       tps       平均延迟 ms
         1      3778         0.265
         4      9732         0.411
        16     12609         1.269

并发提交的事务共用一次 WAL 刷盘,吞吐随连接数上升。

synchronous_commit = off

实测 · 本机执行输出
  show synchronous_commit = off
       连接数       tps       平均延迟 ms
         1      5526         0.181
         4     10779         0.371
        16     13364         1.197

提交不等刷盘,最多丢最近几百毫秒的事务;这台 Mac 上提升不到五成。

fsync_writethrough

实测 · 本机执行输出
  show wal_sync_method = fsync_writethrough ;show synchronous_commit = on ;show fsync = on
       连接数       tps       平均延迟 ms
         1       276         3.619
        16      1221        13.108
  对照 fsync = off(危险,崩溃可能损坏整个数据库):show fsync = off
         1      5290         0.189
        16     13145         1.217

最保守的刷盘方式,吞吐低一个数量级;默认的快刷盘在这台 Mac 上不代表真实磁盘。

批量提交

实测 · 本机执行输出
  每行一次提交          :插入 2000 行用了 0.22 s,约 9168 行/秒
  每 100 行提交一次     :插入 20000 行用了 0.53 s,约 37595 行/秒
  2 万行一次提交        :插入 20000 行用了 0.69 s,约 29048 行/秒

少提交是最实用的优化,每 100 行一提交就把代价摊薄了。

分步演示

提交与刷盘实测
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / PostgreSQL 16.15(Homebrew);每个实验自己 initdb 一个数据目录,端口 9261 起,只监听 127.0.0.1,不碰本机已有的 5432 上的实例;命令行工具统一用 LC_ALL=C 取英文原文,路径换成 ;计时用 time.perf_counter 或 EXPLAIN ANALYZE 的 Execution Time,数字每次运行会有小幅抖动;实验结束后整个数据目录删除。fsync = on、synchronous_commit = on 是显式设置的(pgl 默认把它们关掉);pgbench scale = 10,每组 8 秒,wal_sync_method 的改动通过 ALTER SYSTEM + 重启实例生效;本篇所有数字都来自这台 Mac 的存储,Linux 服务器和真实磁盘的刷盘延迟会不同
    • 没有验证:Linux 上 wal_sync_method 各取值的速度;为什么这台 Mac 的默认 open_datasync 这么快(没有查实现,只量到了结果);commit_delay / commit_siblings 对组提交的影响;同步复制下的提交延迟;电池后备写缓存或企业 SSD 的表现;断电后的真实数据持久性(没有做断电测试)
    京ICP备2026067502号-1京公网安备11010502063487号