PostgreSQL Source Code  git master
pgstat_database.c
Go to the documentation of this file.
1 /* -------------------------------------------------------------------------
2  *
3  * pgstat_database.c
4  * Implementation of database statistics.
5  *
6  * This file contains the implementation of database 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_database.c
15  * -------------------------------------------------------------------------
16  */
17 
18 #include "postgres.h"
19 
20 #include "storage/procsignal.h"
21 #include "utils/pgstat_internal.h"
22 #include "utils/timestamp.h"
23 
24 
25 static bool pgstat_should_report_connstat(void);
26 
27 
33 
34 
35 static int pgStatXactCommit = 0;
36 static int pgStatXactRollback = 0;
38 
39 
40 /*
41  * Remove entry for the database being dropped.
42  */
43 void
45 {
47 }
48 
49 /*
50  * Called from autovacuum.c to report startup of an autovacuum process.
51  * We are called before InitPostgres is done, so can't rely on MyDatabaseId;
52  * the db OID must be passed in, instead.
53  */
54 void
56 {
57  PgStat_EntryRef *entry_ref;
58  PgStatShared_Database *dbentry;
59 
60  /* can't get here in single user mode */
62 
63  /*
64  * End-of-vacuum is reported instantly. Report the start the same way for
65  * consistency. Vacuum doesn't run frequently and is a long-lasting
66  * operation so it doesn't matter if we get blocked here a little.
67  */
69  dboid, InvalidOid, false);
70 
71  dbentry = (PgStatShared_Database *) entry_ref->shared_stats;
73 
74  pgstat_unlock_entry(entry_ref);
75 }
76 
77 /*
78  * Report a Hot Standby recovery conflict.
79  */
80 void
82 {
83  PgStat_StatDBEntry *dbentry;
84 
87  return;
88 
90 
91  switch (reason)
92  {
94 
95  /*
96  * Since we drop the information about the database as soon as it
97  * replicates, there is no point in counting these conflicts.
98  */
99  break;
101  dbentry->conflict_tablespace++;
102  break;
104  dbentry->conflict_lock++;
105  break;
107  dbentry->conflict_snapshot++;
108  break;
110  dbentry->conflict_bufferpin++;
111  break;
113  dbentry->conflict_logicalslot++;
114  break;
116  dbentry->conflict_startup_deadlock++;
117  break;
118  }
119 }
120 
121 /*
122  * Report a detected deadlock.
123  */
124 void
126 {
127  PgStat_StatDBEntry *dbent;
128 
129  if (!pgstat_track_counts)
130  return;
131 
133  dbent->deadlocks++;
134 }
135 
136 /*
137  * Report one or more checksum failures.
138  */
139 void
141 {
142  PgStat_EntryRef *entry_ref;
143  PgStatShared_Database *sharedent;
144 
145  if (!pgstat_track_counts)
146  return;
147 
148  /*
149  * Update the shared stats directly - checksum failures should never be
150  * common enough for that to be a problem.
151  */
152  entry_ref =
154 
155  sharedent = (PgStatShared_Database *) entry_ref->shared_stats;
156  sharedent->stats.checksum_failures += failurecount;
158 
159  pgstat_unlock_entry(entry_ref);
160 }
161 
162 /*
163  * Report one checksum failure in the current database.
164  */
165 void
167 {
169 }
170 
171 /*
172  * Report creation of temporary file.
173  */
174 void
175 pgstat_report_tempfile(size_t filesize)
176 {
177  PgStat_StatDBEntry *dbent;
178 
179  if (!pgstat_track_counts)
180  return;
181 
183  dbent->temp_bytes += filesize;
184  dbent->temp_files++;
185 }
186 
187 /*
188  * Notify stats system of a new connection.
189  */
190 void
192 {
193  PgStat_StatDBEntry *dbentry;
194 
196  return;
197 
199 
201  dbentry->sessions++;
202 }
203 
204 /*
205  * Notify the stats system of a disconnect.
206  */
207 void
209 {
210  PgStat_StatDBEntry *dbentry;
211 
213  return;
214 
216 
217  switch (pgStatSessionEndCause)
218  {
219  case DISCONNECT_NOT_YET:
220  case DISCONNECT_NORMAL:
221  /* we don't collect these */
222  break;
224  dbentry->sessions_abandoned++;
225  break;
226  case DISCONNECT_FATAL:
227  dbentry->sessions_fatal++;
228  break;
229  case DISCONNECT_KILLED:
230  dbentry->sessions_killed++;
231  break;
232  }
233 }
234 
235 /*
236  * Support function for the SQL-callable pgstat* functions. Returns
237  * the collected statistics for one database or NULL. NULL doesn't mean
238  * that the database doesn't exist, just that there are no statistics, so the
239  * caller is better off to report ZERO instead.
240  */
243 {
244  return (PgStat_StatDBEntry *)
246 }
247 
248 void
249 AtEOXact_PgStat_Database(bool isCommit, bool parallel)
250 {
251  /* Don't count parallel worker transaction stats */
252  if (!parallel)
253  {
254  /*
255  * Count transaction commit or abort. (We use counters, not just
256  * bools, in case the reporting message isn't sent right away.)
257  */
258  if (isCommit)
260  else
262  }
263 }
264 
265 /*
266  * Notify the stats system about parallel worker information.
267  */
268 void
270  PgStat_Counter workers_launched)
271 {
272  PgStat_StatDBEntry *dbentry;
273 
274  if (!OidIsValid(MyDatabaseId))
275  return;
276 
278  dbentry->parallel_workers_to_launch += workers_to_launch;
279  dbentry->parallel_workers_launched += workers_launched;
280 }
281 
282 /*
283  * Subroutine for pgstat_report_stat(): Handle xact commit/rollback and I/O
284  * timings.
285  */
286 void
288 {
289  PgStat_StatDBEntry *dbentry;
290 
291  /*
292  * If not connected to a database yet, don't attribute time to "shared
293  * state" (InvalidOid is used to track stats for shared relations, etc.).
294  */
295  if (!OidIsValid(MyDatabaseId))
296  return;
297 
299 
300  /*
301  * Accumulate xact commit/rollback and I/O timings to stats entry of the
302  * current database.
303  */
304  dbentry->xact_commit += pgStatXactCommit;
305  dbentry->xact_rollback += pgStatXactRollback;
308 
310  {
311  long secs;
312  int usecs;
313 
314  /*
315  * pgLastSessionReportTime is initialized to MyStartTimestamp by
316  * pgstat_report_connect().
317  */
318  TimestampDifference(pgLastSessionReportTime, ts, &secs, &usecs);
320  dbentry->session_time += (PgStat_Counter) secs * 1000000 + usecs;
321  dbentry->active_time += pgStatActiveTime;
323  }
324 
325  pgStatXactCommit = 0;
326  pgStatXactRollback = 0;
329  pgStatActiveTime = 0;
331 }
332 
333 /*
334  * We report session statistics only for normal backend processes. Parallel
335  * workers run in parallel, so they don't contribute to session times, even
336  * though they use CPU time. Walsender processes could be considered here,
337  * but they have different session characteristics from normal backends (for
338  * example, they are always "active"), so they would skew session statistics.
339  */
340 static bool
342 {
343  return MyBackendType == B_BACKEND;
344 }
345 
346 /*
347  * Find or create a local PgStat_StatDBEntry entry for dboid.
348  */
351 {
352  PgStat_EntryRef *entry_ref;
353 
354  /*
355  * This should not report stats on database objects before having
356  * connected to a database.
357  */
359 
361  NULL);
362 
363  return entry_ref->pending;
364 }
365 
366 /*
367  * Reset the database's reset timestamp, without resetting the contents of the
368  * database stats.
369  */
370 void
372 {
373  PgStat_EntryRef *dbref;
374  PgStatShared_Database *dbentry;
375 
377  false);
378 
379  dbentry = (PgStatShared_Database *) dbref->shared_stats;
380  dbentry->stats.stat_reset_timestamp = ts;
381 
382  pgstat_unlock_entry(dbref);
383 }
384 
385 /*
386  * Flush out pending stats for the entry
387  *
388  * If nowait is true, this function returns false if lock could not
389  * immediately acquired, otherwise true is returned.
390  */
391 bool
393 {
394  PgStatShared_Database *sharedent;
395  PgStat_StatDBEntry *pendingent;
396 
397  pendingent = (PgStat_StatDBEntry *) entry_ref->pending;
398  sharedent = (PgStatShared_Database *) entry_ref->shared_stats;
399 
400  if (!pgstat_lock_entry(entry_ref, nowait))
401  return false;
402 
403 #define PGSTAT_ACCUM_DBCOUNT(item) \
404  (sharedent)->stats.item += (pendingent)->item
405 
406  PGSTAT_ACCUM_DBCOUNT(xact_commit);
407  PGSTAT_ACCUM_DBCOUNT(xact_rollback);
408  PGSTAT_ACCUM_DBCOUNT(blocks_fetched);
409  PGSTAT_ACCUM_DBCOUNT(blocks_hit);
410 
411  PGSTAT_ACCUM_DBCOUNT(tuples_returned);
412  PGSTAT_ACCUM_DBCOUNT(tuples_fetched);
413  PGSTAT_ACCUM_DBCOUNT(tuples_inserted);
414  PGSTAT_ACCUM_DBCOUNT(tuples_updated);
415  PGSTAT_ACCUM_DBCOUNT(tuples_deleted);
416 
417  /* last_autovac_time is reported immediately */
418  Assert(pendingent->last_autovac_time == 0);
419 
420  PGSTAT_ACCUM_DBCOUNT(conflict_tablespace);
421  PGSTAT_ACCUM_DBCOUNT(conflict_lock);
422  PGSTAT_ACCUM_DBCOUNT(conflict_snapshot);
423  PGSTAT_ACCUM_DBCOUNT(conflict_logicalslot);
424  PGSTAT_ACCUM_DBCOUNT(conflict_bufferpin);
425  PGSTAT_ACCUM_DBCOUNT(conflict_startup_deadlock);
426 
427  PGSTAT_ACCUM_DBCOUNT(temp_bytes);
428  PGSTAT_ACCUM_DBCOUNT(temp_files);
429  PGSTAT_ACCUM_DBCOUNT(deadlocks);
430 
431  /* checksum failures are reported immediately */
432  Assert(pendingent->checksum_failures == 0);
433  Assert(pendingent->last_checksum_failure == 0);
434 
435  PGSTAT_ACCUM_DBCOUNT(blk_read_time);
436  PGSTAT_ACCUM_DBCOUNT(blk_write_time);
437 
438  PGSTAT_ACCUM_DBCOUNT(sessions);
439  PGSTAT_ACCUM_DBCOUNT(session_time);
440  PGSTAT_ACCUM_DBCOUNT(active_time);
441  PGSTAT_ACCUM_DBCOUNT(idle_in_transaction_time);
442  PGSTAT_ACCUM_DBCOUNT(sessions_abandoned);
443  PGSTAT_ACCUM_DBCOUNT(sessions_fatal);
444  PGSTAT_ACCUM_DBCOUNT(sessions_killed);
445  PGSTAT_ACCUM_DBCOUNT(parallel_workers_to_launch);
446  PGSTAT_ACCUM_DBCOUNT(parallel_workers_launched);
447 #undef PGSTAT_ACCUM_DBCOUNT
448 
449  pgstat_unlock_entry(entry_ref);
450 
451  memset(pendingent, 0, sizeof(*pendingent));
452 
453  return true;
454 }
455 
456 void
458 {
459  ((PgStatShared_Database *) header)->stats.stat_reset_timestamp = ts;
460 }
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition: timestamp.c:1720
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1644
#define Assert(condition)
Definition: c.h:812
#define OidIsValid(objectId)
Definition: c.h:729
int64 TimestampTz
Definition: timestamp.h:39
bool IsUnderPostmaster
Definition: globals.c:119
TimestampTz MyStartTimestamp
Definition: globals.c:48
Oid MyDatabaseId
Definition: globals.c:93
@ B_BACKEND
Definition: miscadmin.h:335
BackendType MyBackendType
Definition: miscinit.c:64
bool pgstat_track_counts
Definition: pgstat.c:203
void * pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
Definition: pgstat.c:939
PgStat_EntryRef * pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, uint64 objid, bool *created_entry)
Definition: pgstat.c:1273
SessionEndType
Definition: pgstat.h:108
@ DISCONNECT_NOT_YET
Definition: pgstat.h:109
@ DISCONNECT_FATAL
Definition: pgstat.h:112
@ DISCONNECT_KILLED
Definition: pgstat.h:113
@ DISCONNECT_CLIENT_EOF
Definition: pgstat.h:111
@ DISCONNECT_NORMAL
Definition: pgstat.h:110
#define PGSTAT_KIND_DATABASE
Definition: pgstat.h:47
int64 PgStat_Counter
Definition: pgstat.h:120
static bool pgstat_should_report_connstat(void)
void pgstat_update_parallel_workers_stats(PgStat_Counter workers_to_launch, PgStat_Counter workers_launched)
PgStat_Counter pgStatActiveTime
PgStat_Counter pgStatBlockReadTime
void pgstat_report_autovac(Oid dboid)
void pgstat_database_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)
void pgstat_report_connect(Oid dboid)
PgStat_Counter pgStatBlockWriteTime
void pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount)
void pgstat_report_checksum_failure(void)
static PgStat_Counter pgLastSessionReportTime
static int pgStatXactCommit
void AtEOXact_PgStat_Database(bool isCommit, bool parallel)
void pgstat_report_deadlock(void)
void pgstat_report_recovery_conflict(int reason)
void pgstat_update_dbstats(TimestampTz ts)
PgStat_StatDBEntry * pgstat_prep_database_pending(Oid dboid)
PgStat_Counter pgStatTransactionIdleTime
SessionEndType pgStatSessionEndCause
void pgstat_drop_database(Oid databaseid)
PgStat_StatDBEntry * pgstat_fetch_stat_dbentry(Oid dboid)
void pgstat_reset_database_timestamp(Oid dboid, TimestampTz ts)
void pgstat_report_disconnect(Oid dboid)
#define PGSTAT_ACCUM_DBCOUNT(item)
static int pgStatXactRollback
bool pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
void pgstat_report_tempfile(size_t filesize)
void pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
Definition: pgstat_shmem.c:675
PgStat_EntryRef * pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, uint64 objid, bool nowait)
Definition: pgstat_shmem.c:684
bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait)
Definition: pgstat_shmem.c:647
void pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, uint64 objid)
Definition: pgstat_xact.c:384
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
@ PROCSIG_RECOVERY_CONFLICT_BUFFERPIN
Definition: procsignal.h:47
@ PROCSIG_RECOVERY_CONFLICT_LOCK
Definition: procsignal.h:44
@ PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT
Definition: procsignal.h:46
@ PROCSIG_RECOVERY_CONFLICT_DATABASE
Definition: procsignal.h:42
@ PROCSIG_RECOVERY_CONFLICT_SNAPSHOT
Definition: procsignal.h:45
@ PROCSIG_RECOVERY_CONFLICT_TABLESPACE
Definition: procsignal.h:43
@ PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK
Definition: procsignal.h:48
PgStat_StatDBEntry stats
PgStatShared_Common * shared_stats
PgStat_Counter blk_write_time
Definition: pgstat.h:381
PgStat_Counter xact_rollback
Definition: pgstat.h:360
PgStat_Counter conflict_startup_deadlock
Definition: pgstat.h:374
PgStat_Counter conflict_lock
Definition: pgstat.h:370
PgStat_Counter parallel_workers_to_launch
Definition: pgstat.h:389
TimestampTz stat_reset_timestamp
Definition: pgstat.h:392
PgStat_Counter conflict_snapshot
Definition: pgstat.h:371
PgStat_Counter sessions_fatal
Definition: pgstat.h:387
TimestampTz last_checksum_failure
Definition: pgstat.h:379
PgStat_Counter blk_read_time
Definition: pgstat.h:380
PgStat_Counter parallel_workers_launched
Definition: pgstat.h:390
PgStat_Counter xact_commit
Definition: pgstat.h:359
TimestampTz last_autovac_time
Definition: pgstat.h:368
PgStat_Counter deadlocks
Definition: pgstat.h:377
PgStat_Counter temp_bytes
Definition: pgstat.h:376
PgStat_Counter session_time
Definition: pgstat.h:383
PgStat_Counter temp_files
Definition: pgstat.h:375
PgStat_Counter sessions_abandoned
Definition: pgstat.h:386
PgStat_Counter sessions
Definition: pgstat.h:382
PgStat_Counter active_time
Definition: pgstat.h:384
PgStat_Counter conflict_bufferpin
Definition: pgstat.h:373
PgStat_Counter idle_in_transaction_time
Definition: pgstat.h:385
PgStat_Counter conflict_logicalslot
Definition: pgstat.h:372
PgStat_Counter sessions_killed
Definition: pgstat.h:388
PgStat_Counter checksum_failures
Definition: pgstat.h:378
PgStat_Counter conflict_tablespace
Definition: pgstat.h:369