正常情况下, 数据库为了确保用户对数据库修改操作的持久化, 在事务结束后需要先确保WAL日志buffer已经刷到持久化存储设备后, 才会返回给用户已提交成功.
那么问题来了, 每个事务结束都要发起持久化操作, 会显著增加存放WAL日志的存储设备的IO, 把IO打爆!
为了解决这个问题, PG数据库设计了分组提交的功能, 当有多个事务(有参数可配置)同时处于提交状态时, 不需要每个事务都发起持久化IO请求, 而是聚集到一起, 减少物理IO.
这个手段通常适合于活跃连接较多的高并发小事务工作负载.
但是到底应该设置多少个同时等待的事务, 等待多久呢? 设置不佳会不会影响性能呢?
现在PostgreSQL 19有可观测补丁了!
https://github.com/postgres/postgres/commit/3cb5808bd11c5a7ef697922335f7642f643a4e7f
Add wait event for the group commit delay before WAL flush
Author: Rafia Sabih <rafia.pghackers@gmail.com>
Reviewed-by: Sami Imseih <samimseih@gmail.com>
Discussion: https://www.postgresql.org/message-id/CA%2BFpmFf-hWXtrC0Q3Cr_Xo78zuP_M_VC5xgWPOYOkwqOD0T8eg@mail.gmail.com
这个补丁的目的是:在 PostgreSQL 的组提交(group commit)延迟等待期间添加一个等待事件(wait event)。
1. 提交信息总结 (Commit Message Summary):
2. 核心改动 (Key Changes):
这个补丁涉及两个文件,都与 PostgreSQL 的 WAL(Write-Ahead Logging)处理和活动监控有关。
src/backend/access/transam/xlog.c这是 WAL 刷新的核心逻辑文件。改动发生在 XLogFlush 函数中处理组提交延迟(CommitDelay)的部分。
@@ -2884,7 +2884,9 @@ XLogFlush(XLogRecPtr record)
if (CommitDelay > 0 && enableFsync &&
MinimumActiveBackends(CommitSiblings))
{
+ pgstat_report_wait_start(WAIT_EVENT_COMMIT_DELAY);
pg_usleep(CommitDelay);
+ pgstat_report_wait_end();
/*
* Re-check how far we can now flush the WAL. It's generally not
pgstat_report_wait_start(WAIT_EVENT_COMMIT_DELAY): 在进程开始执行 pg_usleep(CommitDelay)(即等待组提交延迟)之前,报告开始等待 COMMIT_DELAY 事件。pgstat_report_wait_end(): 在延迟等待结束后,报告等待事件结束。意义: 这使得 DBA 或性能分析工具可以通过 pg_stat_activity 视图观察到事务进程是否正在等待组提交延迟。如果一个进程处于这个等待事件中,就说明它正在等待其他事务聚集起来一起执行 WAL 刷新,这是 commit_delay 设置的预期行为。
src/backend/utils/activity/wait_event_names.txt这个文件定义了所有可以报告的等待事件的名称。
@@ -175,6 +175,7 @@ Section: ClassName - WaitEventTimeout
BASE_BACKUP_THROTTLE "Waiting during base backup when throttling activity."
CHECKPOINT_WRITE_DELAY "Waiting between writes while performing a checkpoint."
+COMMIT_DELAY "Waiting for commit delay before WAL flush."
PG_SLEEP "Waiting due to a call to <function>pg_sleep</function> or a sibling function."
RECOVERY_APPLY_DELAY "Waiting to apply WAL during recovery because of a delay setting."
RECOVERY_RETRIEVE_RETRY_INTERVAL "Waiting during recovery when WAL data is not available from any source (<filename>pg_wal</filename>, archive or stream)."
COMMIT_DELAY 事件的定义: 明确了 COMMIT_DELAY 等待事件的描述为 "Waiting for commit delay before WAL flush."(等待 WAL 刷新前的提交延迟)。这个补丁是一项可观测性(Observability)增强功能。它没有改变 PostgreSQL 的组提交或 WAL 刷新的行为,而是增加了对现有行为的监控和诊断能力。
在应用此补丁后,用户可以更清晰地诊断为什么某些事务提交(commit)操作耗时较长:如果进程显示在 COMMIT_DELAY 等待事件中,那么慢的原因就是配置的组提交延迟(commit_delay)在生效,而不是 WAL 刷新本身慢,这有助于调优和故障排除。