PostgreSQL Source Code  git master
pgstat_wal.c
Go to the documentation of this file.
1 /* -------------------------------------------------------------------------
2  *
3  * pgstat_wal.c
4  * Implementation of WAL statistics.
5  *
6  * This file contains the implementation of WAL statistics. It is kept
7  * separate from pgstat.c to enforce the line between the statistics access /
8  * storage implementation and the details about individual types of
9  * statistics.
10  *
11  * Copyright (c) 2001-2024, PostgreSQL Global Development Group
12  *
13  * IDENTIFICATION
14  * src/backend/utils/activity/pgstat_wal.c
15  * -------------------------------------------------------------------------
16  */
17 
18 #include "postgres.h"
19 
20 #include "executor/instrument.h"
21 #include "utils/pgstat_internal.h"
22 
23 
25 
26 /*
27  * WAL usage counters saved from pgWalUsage at the previous call to
28  * pgstat_report_wal(). This is used to calculate how much WAL usage
29  * happens between pgstat_report_wal() calls, by subtracting
30  * the previous counters from the current ones.
31  */
33 
34 
35 /*
36  * Calculate how much WAL usage counters have increased and update
37  * shared WAL and IO statistics.
38  *
39  * Must be called by processes that generate WAL, that do not call
40  * pgstat_report_stat(), like walwriter.
41  *
42  * "force" set to true ensures that the statistics are flushed; note that
43  * this needs to acquire the pgstat shmem LWLock, waiting on it. When
44  * set to false, the statistics may not be flushed if the lock could not
45  * be acquired.
46  */
47 void
48 pgstat_report_wal(bool force)
49 {
50  bool nowait;
51 
52  /* like in pgstat.c, don't wait for lock acquisition when !force */
53  nowait = !force;
54 
55  /* flush wal stats */
56  pgstat_flush_wal(nowait);
57 
58  /* flush IO stats */
59  pgstat_flush_io(nowait);
60 }
61 
62 /*
63  * Support function for the SQL-callable pgstat* functions. Returns
64  * a pointer to the WAL statistics struct.
65  */
68 {
70 
71  return &pgStatLocal.snapshot.wal;
72 }
73 
74 /*
75  * Calculate how much WAL usage counters have increased by subtracting the
76  * previous counters from the current ones.
77  *
78  * If nowait is true, this function returns true if the lock could not be
79  * acquired. Otherwise return false.
80  */
81 bool
82 pgstat_flush_wal(bool nowait)
83 {
84  PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
85  WalUsage wal_usage_diff = {0};
86 
88  Assert(pgStatLocal.shmem != NULL &&
90 
91  /*
92  * This function can be called even if nothing at all has happened. Avoid
93  * taking lock for nothing in that case.
94  */
96  return false;
97 
98  /*
99  * We don't update the WAL usage portion of the local WalStats elsewhere.
100  * Calculate how much WAL usage counters were increased by subtracting the
101  * previous counters from the current ones.
102  */
103  WalUsageAccumDiff(&wal_usage_diff, &pgWalUsage, &prevWalUsage);
104 
105  if (!nowait)
106  LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
107  else if (!LWLockConditionalAcquire(&stats_shmem->lock, LW_EXCLUSIVE))
108  return true;
109 
110 #define WALSTAT_ACC(fld, var_to_add) \
111  (stats_shmem->stats.fld += var_to_add.fld)
112 #define WALSTAT_ACC_INSTR_TIME(fld) \
113  (stats_shmem->stats.fld += INSTR_TIME_GET_MICROSEC(PendingWalStats.fld))
114  WALSTAT_ACC(wal_records, wal_usage_diff);
115  WALSTAT_ACC(wal_fpi, wal_usage_diff);
116  WALSTAT_ACC(wal_bytes, wal_usage_diff);
117  WALSTAT_ACC(wal_buffers_full, PendingWalStats);
118  WALSTAT_ACC(wal_write, PendingWalStats);
119  WALSTAT_ACC(wal_sync, PendingWalStats);
120  WALSTAT_ACC_INSTR_TIME(wal_write_time);
121  WALSTAT_ACC_INSTR_TIME(wal_sync_time);
122 #undef WALSTAT_ACC_INSTR_TIME
123 #undef WALSTAT_ACC
124 
125  LWLockRelease(&stats_shmem->lock);
126 
127  /*
128  * Save the current counters for the subsequent calculation of WAL usage.
129  */
131 
132  /*
133  * Clear out the statistics buffer, so it can be re-used.
134  */
135  MemSet(&PendingWalStats, 0, sizeof(PendingWalStats));
136 
137  return false;
138 }
139 
140 void
142 {
143  /*
144  * Initialize prevWalUsage with pgWalUsage so that pgstat_flush_wal() can
145  * calculate how much pgWalUsage counters are increased by subtracting
146  * prevWalUsage from pgWalUsage.
147  */
149 }
150 
151 /*
152  * To determine whether any WAL activity has occurred since last time, not
153  * only the number of generated WAL records but also the numbers of WAL
154  * writes and syncs need to be checked. Because even transaction that
155  * generates no WAL records can write or sync WAL data when flushing the
156  * data pages.
157  */
158 bool
160 {
162  PendingWalStats.wal_write != 0 ||
164 }
165 
166 void
168 {
169  PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
170 
171  LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
172  memset(&stats_shmem->stats, 0, sizeof(stats_shmem->stats));
173  stats_shmem->stats.stat_reset_timestamp = ts;
174  LWLockRelease(&stats_shmem->lock);
175 }
176 
177 void
179 {
180  PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
181 
182  LWLockAcquire(&stats_shmem->lock, LW_SHARED);
183  memcpy(&pgStatLocal.snapshot.wal, &stats_shmem->stats,
184  sizeof(pgStatLocal.snapshot.wal));
185  LWLockRelease(&stats_shmem->lock);
186 }
#define Assert(condition)
Definition: c.h:858
#define MemSet(start, val, len)
Definition: c.h:1020
int64 TimestampTz
Definition: timestamp.h:39
bool IsUnderPostmaster
Definition: globals.c:117
bool IsPostmasterEnvironment
Definition: globals.c:116
WalUsage pgWalUsage
Definition: instrument.c:22
void WalUsageAccumDiff(WalUsage *dst, const WalUsage *add, const WalUsage *sub)
Definition: instrument.c:286
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1170
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1783
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1341
@ LW_SHARED
Definition: lwlock.h:115
@ LW_EXCLUSIVE
Definition: lwlock.h:114
void pgstat_snapshot_fixed(PgStat_Kind kind)
Definition: pgstat.c:938
PgStat_LocalState pgStatLocal
Definition: pgstat.c:193
@ PGSTAT_KIND_WAL
Definition: pgstat.h:53
bool pgstat_flush_io(bool nowait)
Definition: pgstat_io.c:173
#define WALSTAT_ACC(fld, var_to_add)
void pgstat_wal_reset_all_cb(TimestampTz ts)
Definition: pgstat_wal.c:167
bool pgstat_have_pending_wal(void)
Definition: pgstat_wal.c:159
void pgstat_init_wal(void)
Definition: pgstat_wal.c:141
void pgstat_report_wal(bool force)
Definition: pgstat_wal.c:48
PgStat_WalStats * pgstat_fetch_stat_wal(void)
Definition: pgstat_wal.c:67
bool pgstat_flush_wal(bool nowait)
Definition: pgstat_wal.c:82
static WalUsage prevWalUsage
Definition: pgstat_wal.c:32
void pgstat_wal_snapshot_cb(void)
Definition: pgstat_wal.c:178
PgStat_PendingWalStats PendingWalStats
Definition: pgstat_wal.c:24
#define WALSTAT_ACC_INSTR_TIME(fld)
PgStat_WalStats stats
PgStat_Snapshot snapshot
PgStat_ShmemControl * shmem
PgStat_Counter wal_write
Definition: pgstat.h:453
PgStat_Counter wal_sync
Definition: pgstat.h:454
PgStatShared_Wal wal
PgStat_WalStats wal
TimestampTz stat_reset_timestamp
Definition: pgstat.h:441
int64 wal_records
Definition: instrument.h:53