LCOV - differential code coverage report
Current view: top level - src/backend/utils/activity - pgstat_database.c (source / functions) Coverage Total Hit UIC UBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 95.6 % 160 153 5 2 44 51 58 3 65 2 30
Current Date: 2023-04-08 17:13:01 Functions: 94.1 % 17 16 1 13 1 2 1 13
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 4 4 3 1
Legend: Lines: hit not hit (120,180] days: 100.0 % 47 47 47
(240..) days: 93.6 % 109 102 5 2 44 1 57 3 62
Function coverage date bins:
(240..) days: 53.3 % 30 16 1 13 1 2 1 12

 Age         Owner                  TLA  Line data    Source code
                                  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-2023, 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 "utils/pgstat_internal.h"
                                 21                 : #include "utils/timestamp.h"
                                 22                 : #include "storage/procsignal.h"
                                 23                 : 
                                 24                 : 
                                 25                 : static bool pgstat_should_report_connstat(void);
                                 26                 : 
                                 27                 : 
                                 28                 : PgStat_Counter pgStatBlockReadTime = 0;
                                 29                 : PgStat_Counter pgStatBlockWriteTime = 0;
                                 30                 : PgStat_Counter pgStatActiveTime = 0;
                                 31                 : PgStat_Counter pgStatTransactionIdleTime = 0;
                                 32                 : SessionEndType pgStatSessionEndCause = DISCONNECT_NORMAL;
                                 33                 : 
                                 34                 : 
                                 35                 : static int  pgStatXactCommit = 0;
                                 36                 : static int  pgStatXactRollback = 0;
                                 37                 : static PgStat_Counter pgLastSessionReportTime = 0;
                                 38                 : 
                                 39                 : 
                                 40                 : /*
                                 41                 :  * Remove entry for the database being dropped.
                                 42                 :  */
                                 43                 : void
  384 andres                     44 CBC          20 : pgstat_drop_database(Oid databaseid)
                                 45                 : {
  368                            46              20 :     pgstat_drop_transactional(PGSTAT_KIND_DATABASE, databaseid, InvalidOid);
  384                            47              20 : }
                                 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
  368                            55              16 : pgstat_report_autovac(Oid dboid)
                                 56                 : {
                                 57                 :     PgStat_EntryRef *entry_ref;
                                 58                 :     PgStatShared_Database *dbentry;
                                 59                 : 
                                 60                 :     /* can't get here in single user mode */
                                 61              16 :     Assert(IsUnderPostmaster);
                                 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                 :      */
                                 68              16 :     entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE,
                                 69                 :                                             dboid, InvalidOid, false);
                                 70                 : 
                                 71              16 :     dbentry = (PgStatShared_Database *) entry_ref->shared_stats;
                                 72              16 :     dbentry->stats.last_autovac_time = GetCurrentTimestamp();
                                 73                 : 
                                 74              16 :     pgstat_unlock_entry(entry_ref);
                                 75              16 : }
                                 76                 : 
                                 77                 : /*
                                 78                 :  * Report a Hot Standby recovery conflict.
                                 79                 :  */
                                 80                 : void
  384                            81              12 : pgstat_report_recovery_conflict(int reason)
                                 82                 : {
                                 83                 :     PgStat_StatDBEntry *dbentry;
                                 84                 : 
  368                            85              12 :     Assert(IsUnderPostmaster);
                                 86              12 :     if (!pgstat_track_counts)
  384 andres                     87 UBC           0 :         return;
                                 88                 : 
  368 andres                     89 CBC          12 :     dbentry = pgstat_prep_database_pending(MyDatabaseId);
                                 90                 : 
                                 91              12 :     switch (reason)
                                 92                 :     {
                                 93               2 :         case PROCSIG_RECOVERY_CONFLICT_DATABASE:
                                 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               2 :             break;
                                100               1 :         case PROCSIG_RECOVERY_CONFLICT_TABLESPACE:
  123 michael                   101 GNC           1 :             dbentry->conflict_tablespace++;
  368 andres                    102 CBC           1 :             break;
                                103               1 :         case PROCSIG_RECOVERY_CONFLICT_LOCK:
  123 michael                   104 GNC           1 :             dbentry->conflict_lock++;
  368 andres                    105 CBC           1 :             break;
                                106               1 :         case PROCSIG_RECOVERY_CONFLICT_SNAPSHOT:
  123 michael                   107 GNC           1 :             dbentry->conflict_snapshot++;
  368 andres                    108 CBC           1 :             break;
                                109               1 :         case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN:
  123 michael                   110 GNC           1 :             dbentry->conflict_bufferpin++;
  368 andres                    111               1 :             break;
    2                           112               5 :         case PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT:
                                113               5 :             dbentry->conflict_logicalslot++;
    2 andres                    114 CBC           5 :             break;
  368                           115               1 :         case PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK:
  123 michael                   116 GNC           1 :             dbentry->conflict_startup_deadlock++;
  368 andres                    117 CBC           1 :             break;
  368 andres                    118 ECB             :     }
  384                           119                 : }
                                120                 : 
                                121                 : /*
                                122                 :  * Report a detected deadlock.
                                123                 :  */
                                124                 : void
  384 andres                    125 GIC           5 : pgstat_report_deadlock(void)
                                126                 : {
                                127                 :     PgStat_StatDBEntry *dbent;
  384 andres                    128 ECB             : 
  368 andres                    129 GIC           5 :     if (!pgstat_track_counts)
  384 andres                    130 UIC           0 :         return;
                                131                 : 
  368 andres                    132 CBC           5 :     dbent = pgstat_prep_database_pending(MyDatabaseId);
  123 michael                   133 GNC           5 :     dbent->deadlocks++;
                                134                 : }
  384 andres                    135 ECB             : 
  370                           136                 : /*
                                137                 :  * Report one or more checksum failures.
                                138                 :  */
                                139                 : void
  384 andres                    140 GIC           2 : pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount)
                                141                 : {
                                142                 :     PgStat_EntryRef *entry_ref;
  368 andres                    143 ECB             :     PgStatShared_Database *sharedent;
                                144                 : 
  368 andres                    145 GIC           2 :     if (!pgstat_track_counts)
  384 andres                    146 UIC           0 :         return;
                                147                 : 
  368 andres                    148 ECB             :     /*
  368 andres                    149 EUB             :      * Update the shared stats directly - checksum failures should never be
                                150                 :      * common enough for that to be a problem.
                                151                 :      */
                                152                 :     entry_ref =
  368 andres                    153 GIC           2 :         pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE, dboid, InvalidOid, false);
                                154                 : 
                                155               2 :     sharedent = (PgStatShared_Database *) entry_ref->shared_stats;
  123 michael                   156 GNC           2 :     sharedent->stats.checksum_failures += failurecount;
  368 andres                    157 GIC           2 :     sharedent->stats.last_checksum_failure = GetCurrentTimestamp();
  384 andres                    158 ECB             : 
  368 andres                    159 CBC           2 :     pgstat_unlock_entry(entry_ref);
  384 andres                    160 ECB             : }
                                161                 : 
  370                           162                 : /*
                                163                 :  * Report one checksum failure in the current database.
                                164                 :  */
                                165                 : void
  384 andres                    166 UIC           0 : pgstat_report_checksum_failure(void)
                                167                 : {
                                168               0 :     pgstat_report_checksum_failures_in_db(MyDatabaseId, 1);
  384 andres                    169 UBC           0 : }
                                170                 : 
  370 andres                    171 EUB             : /*
  368                           172                 :  * Report creation of temporary file.
                                173                 :  */
                                174                 : void
  384 andres                    175 GIC        3222 : pgstat_report_tempfile(size_t filesize)
                                176                 : {
                                177                 :     PgStat_StatDBEntry *dbent;
  384 andres                    178 ECB             : 
  368 andres                    179 GIC        3222 :     if (!pgstat_track_counts)
  384 andres                    180 UIC           0 :         return;
                                181                 : 
  368 andres                    182 CBC        3222 :     dbent = pgstat_prep_database_pending(MyDatabaseId);
  123 michael                   183 GNC        3222 :     dbent->temp_bytes += filesize;
                                184            3222 :     dbent->temp_files++;
  384 andres                    185 ECB             : }
                                186                 : 
  370                           187                 : /*
                                188                 :  * Notify stats system of a new connection.
                                189                 :  */
                                190                 : void
  384 andres                    191 GIC        8866 : pgstat_report_connect(Oid dboid)
                                192                 : {
                                193                 :     PgStat_StatDBEntry *dbentry;
  384 andres                    194 ECB             : 
  384 andres                    195 GIC        8866 :     if (!pgstat_should_report_connstat())
                                196            1143 :         return;
                                197                 : 
  384 andres                    198 CBC        7723 :     pgLastSessionReportTime = MyStartTimestamp;
  384 andres                    199 ECB             : 
  368 andres                    200 GIC        7723 :     dbentry = pgstat_prep_database_pending(MyDatabaseId);
  123 michael                   201 GNC        7723 :     dbentry->sessions++;
                                202                 : }
  384 andres                    203 ECB             : 
  370                           204                 : /*
                                205                 :  * Notify the stats system of a disconnect.
                                206                 :  */
                                207                 : void
  384 andres                    208 GIC       10456 : pgstat_report_disconnect(Oid dboid)
                                209                 : {
                                210                 :     PgStat_StatDBEntry *dbentry;
  384 andres                    211 ECB             : 
  384 andres                    212 GIC       10456 :     if (!pgstat_should_report_connstat())
                                213            2733 :         return;
                                214                 : 
  368 andres                    215 CBC        7723 :     dbentry = pgstat_prep_database_pending(MyDatabaseId);
  368 andres                    216 ECB             : 
  368 andres                    217 GIC        7723 :     switch (pgStatSessionEndCause)
  368 andres                    218 ECB             :     {
  368 andres                    219 GIC        7684 :         case DISCONNECT_NOT_YET:
  368 andres                    220 ECB             :         case DISCONNECT_NORMAL:
                                221                 :             /* we don't collect these */
  368 andres                    222 CBC        7684 :             break;
  368 andres                    223 GIC          23 :         case DISCONNECT_CLIENT_EOF:
  123 michael                   224 GNC          23 :             dbentry->sessions_abandoned++;
  368 andres                    225 CBC          23 :             break;
                                226               5 :         case DISCONNECT_FATAL:
  123 michael                   227 GNC           5 :             dbentry->sessions_fatal++;
  368 andres                    228 CBC           5 :             break;
                                229              11 :         case DISCONNECT_KILLED:
  123 michael                   230 GNC          11 :             dbentry->sessions_killed++;
  368 andres                    231 CBC          11 :             break;
  368 andres                    232 ECB             :     }
                                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                 :  */
                                241                 : PgStat_StatDBEntry *
  368 andres                    242 GIC        1396 : pgstat_fetch_stat_dbentry(Oid dboid)
                                243                 : {
                                244            1396 :     return (PgStat_StatDBEntry *)
  368 andres                    245 CBC        1396 :         pgstat_fetch_entry(PGSTAT_KIND_DATABASE, dboid, InvalidOid);
                                246                 : }
  384 andres                    247 ECB             : 
                                248                 : void
  384 andres                    249 GIC      486199 : AtEOXact_PgStat_Database(bool isCommit, bool parallel)
                                250                 : {
                                251                 :     /* Don't count parallel worker transaction stats */
  384 andres                    252 CBC      486199 :     if (!parallel)
                                253                 :     {
                                254                 :         /*
  384 andres                    255 ECB             :          * Count transaction commit or abort.  (We use counters, not just
                                256                 :          * bools, in case the reporting message isn't sent right away.)
                                257                 :          */
  384 andres                    258 GIC      484901 :         if (isCommit)
                                259          464737 :             pgStatXactCommit++;
                                260                 :         else
  384 andres                    261 CBC       20164 :             pgStatXactRollback++;
  384 andres                    262 ECB             :     }
  384 andres                    263 GIC      486199 : }
  384 andres                    264 ECB             : 
                                265                 : /*
  368                           266                 :  * Subroutine for pgstat_report_stat(): Handle xact commit/rollback and I/O
                                267                 :  * timings.
                                268                 :  */
                                269                 : void
  368 andres                    270 GIC       24455 : pgstat_update_dbstats(TimestampTz ts)
                                271                 : {
                                272                 :     PgStat_StatDBEntry *dbentry;
  384 andres                    273 ECB             : 
  368 andres                    274 GIC       24455 :     dbentry = pgstat_prep_database_pending(MyDatabaseId);
                                275                 : 
                                276                 :     /*
  368 andres                    277 ECB             :      * Accumulate xact commit/rollback and I/O timings to stats entry of the
                                278                 :      * current database.
                                279                 :      */
  123 michael                   280 GNC       24455 :     dbentry->xact_commit += pgStatXactCommit;
                                281           24455 :     dbentry->xact_rollback += pgStatXactRollback;
                                282           24455 :     dbentry->blk_read_time += pgStatBlockReadTime;
                                283           24455 :     dbentry->blk_write_time += pgStatBlockWriteTime;
  368 andres                    284 ECB             : 
  368 andres                    285 CBC       24455 :     if (pgstat_should_report_connstat())
  384 andres                    286 ECB             :     {
                                287                 :         long        secs;
  368                           288                 :         int         usecs;
                                289                 : 
                                290                 :         /*
                                291                 :          * pgLastSessionReportTime is initialized to MyStartTimestamp by
                                292                 :          * pgstat_report_connect().
                                293                 :          */
  368 andres                    294 GIC       16572 :         TimestampDifference(pgLastSessionReportTime, ts, &secs, &usecs);
                                295           16572 :         pgLastSessionReportTime = ts;
  123 michael                   296 GNC       16572 :         dbentry->session_time += (PgStat_Counter) secs * 1000000 + usecs;
                                297           16572 :         dbentry->active_time += pgStatActiveTime;
                                298           16572 :         dbentry->idle_in_transaction_time += pgStatTransactionIdleTime;
  384 andres                    299 ECB             :     }
  368                           300                 : 
  368 andres                    301 CBC       24455 :     pgStatXactCommit = 0;
  368 andres                    302 GIC       24455 :     pgStatXactRollback = 0;
                                303           24455 :     pgStatBlockReadTime = 0;
  368 andres                    304 CBC       24455 :     pgStatBlockWriteTime = 0;
                                305           24455 :     pgStatActiveTime = 0;
                                306           24455 :     pgStatTransactionIdleTime = 0;
  384                           307           24455 : }
  384 andres                    308 ECB             : 
  370                           309                 : /*
                                310                 :  * We report session statistics only for normal backend processes.  Parallel
                                311                 :  * workers run in parallel, so they don't contribute to session times, even
                                312                 :  * though they use CPU time. Walsender processes could be considered here,
                                313                 :  * but they have different session characteristics from normal backends (for
                                314                 :  * example, they are always "active"), so they would skew session statistics.
                                315                 :  */
                                316                 : static bool
  384 andres                    317 GIC       43777 : pgstat_should_report_connstat(void)
                                318                 : {
                                319           43777 :     return MyBackendType == B_BACKEND;
  384 andres                    320 ECB             : }
                                321                 : 
  368                           322                 : /*
                                323                 :  * Find or create a local PgStat_StatDBEntry entry for dboid.
                                324                 :  */
                                325                 : PgStat_StatDBEntry *
  368 andres                    326 GIC      751190 : pgstat_prep_database_pending(Oid dboid)
                                327                 : {
                                328                 :     PgStat_EntryRef *entry_ref;
  368 andres                    329 ECB             : 
  368 andres                    330 GIC      751190 :     entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_DATABASE, dboid, InvalidOid,
                                331                 :                                           NULL);
                                332                 : 
  368 andres                    333 CBC      751190 :     return entry_ref->pending;
                                334                 : }
                                335                 : 
  368 andres                    336 ECB             : /*
                                337                 :  * Reset the database's reset timestamp, without resetting the contents of the
                                338                 :  * database stats.
                                339                 :  */
                                340                 : void
  368 andres                    341 GIC           5 : pgstat_reset_database_timestamp(Oid dboid, TimestampTz ts)
                                342                 : {
                                343                 :     PgStat_EntryRef *dbref;
  368 andres                    344 ECB             :     PgStatShared_Database *dbentry;
                                345                 : 
  368 andres                    346 GIC           5 :     dbref = pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE, MyDatabaseId, InvalidOid,
                                347                 :                                         false);
                                348                 : 
  368 andres                    349 CBC           5 :     dbentry = (PgStatShared_Database *) dbref->shared_stats;
  368 andres                    350 GIC           5 :     dbentry->stats.stat_reset_timestamp = ts;
                                351                 : 
  368 andres                    352 CBC           5 :     pgstat_unlock_entry(dbref);
                                353               5 : }
                                354                 : 
  368 andres                    355 ECB             : /*
                                356                 :  * Flush out pending stats for the entry
                                357                 :  *
                                358                 :  * If nowait is true, this function returns false if lock could not
                                359                 :  * immediately acquired, otherwise true is returned.
                                360                 :  */
                                361                 : bool
  368 andres                    362 GIC       41606 : pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
                                363                 : {
                                364                 :     PgStatShared_Database *sharedent;
  368 andres                    365 ECB             :     PgStat_StatDBEntry *pendingent;
                                366                 : 
  368 andres                    367 GIC       41606 :     pendingent = (PgStat_StatDBEntry *) entry_ref->pending;
                                368           41606 :     sharedent = (PgStatShared_Database *) entry_ref->shared_stats;
                                369                 : 
  368 andres                    370 CBC       41606 :     if (!pgstat_lock_entry(entry_ref, nowait))
                                371               2 :         return false;
                                372                 : 
  368 andres                    373 ECB             : #define PGSTAT_ACCUM_DBCOUNT(item)      \
                                374                 :     (sharedent)->stats.item += (pendingent)->item
                                375                 : 
  123 michael                   376 GNC       41604 :     PGSTAT_ACCUM_DBCOUNT(xact_commit);
                                377           41604 :     PGSTAT_ACCUM_DBCOUNT(xact_rollback);
                                378           41604 :     PGSTAT_ACCUM_DBCOUNT(blocks_fetched);
                                379           41604 :     PGSTAT_ACCUM_DBCOUNT(blocks_hit);
  368 andres                    380 ECB             : 
  123 michael                   381 GNC       41604 :     PGSTAT_ACCUM_DBCOUNT(tuples_returned);
                                382           41604 :     PGSTAT_ACCUM_DBCOUNT(tuples_fetched);
                                383           41604 :     PGSTAT_ACCUM_DBCOUNT(tuples_inserted);
                                384           41604 :     PGSTAT_ACCUM_DBCOUNT(tuples_updated);
                                385           41604 :     PGSTAT_ACCUM_DBCOUNT(tuples_deleted);
  368 andres                    386 ECB             : 
                                387                 :     /* last_autovac_time is reported immediately */
  368 andres                    388 CBC       41604 :     Assert(pendingent->last_autovac_time == 0);
                                389                 : 
  123 michael                   390 GNC       41604 :     PGSTAT_ACCUM_DBCOUNT(conflict_tablespace);
                                391           41604 :     PGSTAT_ACCUM_DBCOUNT(conflict_lock);
                                392           41604 :     PGSTAT_ACCUM_DBCOUNT(conflict_snapshot);
    2 andres                    393           41604 :     PGSTAT_ACCUM_DBCOUNT(conflict_logicalslot);
  123 michael                   394           41604 :     PGSTAT_ACCUM_DBCOUNT(conflict_bufferpin);
                                395           41604 :     PGSTAT_ACCUM_DBCOUNT(conflict_startup_deadlock);
  368 andres                    396 ECB             : 
  123 michael                   397 GNC       41604 :     PGSTAT_ACCUM_DBCOUNT(temp_bytes);
                                398           41604 :     PGSTAT_ACCUM_DBCOUNT(temp_files);
                                399           41604 :     PGSTAT_ACCUM_DBCOUNT(deadlocks);
                                400                 : 
  368 andres                    401 ECB             :     /* checksum failures are reported immediately */
  123 michael                   402 GNC       41604 :     Assert(pendingent->checksum_failures == 0);
  368 andres                    403 CBC       41604 :     Assert(pendingent->last_checksum_failure == 0);
                                404                 : 
  123 michael                   405 GNC       41604 :     PGSTAT_ACCUM_DBCOUNT(blk_read_time);
                                406           41604 :     PGSTAT_ACCUM_DBCOUNT(blk_write_time);
  368 andres                    407 ECB             : 
  123 michael                   408 GNC       41604 :     PGSTAT_ACCUM_DBCOUNT(sessions);
                                409           41604 :     PGSTAT_ACCUM_DBCOUNT(session_time);
                                410           41604 :     PGSTAT_ACCUM_DBCOUNT(active_time);
                                411           41604 :     PGSTAT_ACCUM_DBCOUNT(idle_in_transaction_time);
                                412           41604 :     PGSTAT_ACCUM_DBCOUNT(sessions_abandoned);
                                413           41604 :     PGSTAT_ACCUM_DBCOUNT(sessions_fatal);
                                414           41604 :     PGSTAT_ACCUM_DBCOUNT(sessions_killed);
  368 andres                    415 ECB             : #undef PGSTAT_ACCUM_DBCOUNT
                                416                 : 
  368 andres                    417 CBC       41604 :     pgstat_unlock_entry(entry_ref);
  368 andres                    418 ECB             : 
  368 andres                    419 GIC       41604 :     memset(pendingent, 0, sizeof(*pendingent));
                                420                 : 
  368 andres                    421 CBC       41604 :     return true;
                                422                 : }
  368 andres                    423 ECB             : 
                                424                 : void
  368 andres                    425 CBC          13 : pgstat_database_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)
                                426                 : {
  368 andres                    427 GIC          13 :     ((PgStatShared_Database *) header)->stats.stat_reset_timestamp = ts;
                                428              13 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a