“PostgreSQL 的 synchronous_commit 和 fsync 到底影响多大、批量提交能快多少” 经常被泛泛而谈。这篇在本机自己起一个 PostgreSQL 16.15,用 pg_test_fsync 和 pgbench 量各种刷盘方式、同步提交开关、并发连接数(组提交)和批量提交的吞吐,同时如实指出这台 Mac 的默认刷盘方式与真实磁盘的差别。
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 刷盘,吞吐随连接数上升。
show synchronous_commit = off
连接数 tps 平均延迟 ms
1 5526 0.181
4 10779 0.371
16 13364 1.197提交不等刷盘,最多丢最近几百毫秒的事务;这台 Mac 上提升不到五成。
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 行一提交就把代价摊薄了。