Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  pgstat_database.c

  Sprache: C
 

/* -------------------------------------------------------------------------
 *
 * pgstat_database.c
 *   Implementation of database statistics.
 *
 * This file contains the implementation of database statistics. It is kept
 * separate from pgstat.c to enforce the line between the statistics access /
 * storage implementation and the details about individual types of
 * statistics.
 *
 * Copyright (c) 2001-2025, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *   src/backend/utils/activity/pgstat_database.c
 * -------------------------------------------------------------------------
 */


#include "postgres.h"

#include "storage/procsignal.h"
#include "utils/pgstat_internal.h"
#include "utils/timestamp.h"


static bool pgstat_should_report_connstat(void);


PgStat_Counter pgStatBlockReadTime = 0;
PgStat_Counter pgStatBlockWriteTime = 0;
PgStat_Counter pgStatActiveTime = 0;
PgStat_Counter pgStatTransactionIdleTime = 0;
SessionEndType pgStatSessionEndCause = DISCONNECT_NORMAL;


static int pgStatXactCommit = 0;
static int pgStatXactRollback = 0;
static PgStat_Counter pgLastSessionReportTime = 0;


/*
 * Remove entry for the database being dropped.
 */

void
pgstat_drop_database(Oid databaseid)
{
 pgstat_drop_transactional(PGSTAT_KIND_DATABASE, databaseid, InvalidOid);
}

/*
 * Called from autovacuum.c to report startup of an autovacuum process.
 * We are called before InitPostgres is done, so can't rely on MyDatabaseId;
 * the db OID must be passed in, instead.
 */

void
pgstat_report_autovac(Oid dboid)
{
 PgStat_EntryRef *entry_ref;
 PgStatShared_Database *dbentry;

 /* can't get here in single user mode */
 Assert(IsUnderPostmaster);

 /*
  * End-of-vacuum is reported instantly. Report the start the same way for
  * consistency. Vacuum doesn't run frequently and is a long-lasting
  * operation so it doesn't matter if we get blocked here a little.
 */

 entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE,
           dboid, InvalidOid, false);

 dbentry = (PgStatShared_Database *) entry_ref->shared_stats;
 dbentry->stats.last_autovac_time = GetCurrentTimestamp();

 pgstat_unlock_entry(entry_ref);
}

/*
 * Report a Hot Standby recovery conflict.
 */

void
pgstat_report_recovery_conflict(int reason)
{
 PgStat_StatDBEntry *dbentry;

 Assert(IsUnderPostmaster);
 if (!pgstat_track_counts)
  return;

 dbentry = pgstat_prep_database_pending(MyDatabaseId);

 switch (reason)
 {
  case PROCSIG_RECOVERY_CONFLICT_DATABASE:

   /*
    * Since we drop the information about the database as soon as it
    * replicates, there is no point in counting these conflicts.
 */

   break;
  case PROCSIG_RECOVERY_CONFLICT_TABLESPACE:
   dbentry->conflict_tablespace++;
   break;
  case PROCSIG_RECOVERY_CONFLICT_LOCK:
   dbentry->conflict_lock++;
   break;
  case PROCSIG_RECOVERY_CONFLICT_SNAPSHOT:
   dbentry->conflict_snapshot++;
   break;
  case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN:
   dbentry->conflict_bufferpin++;
   break;
  case PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT:
   dbentry->conflict_logicalslot++;
   break;
  case PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK:
   dbentry->conflict_startup_deadlock++;
   break;
 }
}

/*
 * Report a detected deadlock.
 */

void
pgstat_report_deadlock(void)
{
 PgStat_StatDBEntry *dbent;

 if (!pgstat_track_counts)
  return;

 dbent = pgstat_prep_database_pending(MyDatabaseId);
 dbent->deadlocks++;
}

/*
 * Allow this backend to later report checksum failures for dboid, even if in
 * a critical section at the time of the report.
 *
 * Without this function having been called first, the backend might need to
 * allocate an EntryRef or might need to map in DSM segments. Neither should
 * happen in a critical section.
 */

void
pgstat_prepare_report_checksum_failure(Oid dboid)
{
 Assert(!CritSectionCount);

 /*
  * Just need to ensure this backend has an entry ref for the database.
  * That will allows us to report checksum failures without e.g. needing to
  * map in DSM segments.
 */

 pgstat_get_entry_ref(PGSTAT_KIND_DATABASE, dboid, InvalidOid,
       true, NULL);
}

/*
 * Report one or more checksum failures.
 *
 * To be allowed to report checksum failures in critical sections, we require
 * pgstat_prepare_report_checksum_failure() to have been called before this
 * function is called.
 */

void
pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount)
{
 PgStat_EntryRef *entry_ref;
 PgStatShared_Database *sharedent;

 if (!pgstat_track_counts)
  return;

 /*
  * Update the shared stats directly - checksum failures should never be
  * common enough for that to be a problem. Note that we pass create=false
  * here, as we want to be sure to not require memory allocations, so this
  * can be called in critical sections.
 */

 entry_ref = pgstat_get_entry_ref(PGSTAT_KIND_DATABASE, dboid, InvalidOid,
          false, NULL);

 /*
  * Should always have been created by
  * pgstat_prepare_report_checksum_failure().
  *
  * When not using assertions, we don't want to crash should something have
  * gone wrong, so just return.
 */

 Assert(entry_ref);
 if (!entry_ref)
 {
  elog(WARNING, "could not report %d checksum failures for database %u",
    failurecount, dboid);
  return;
 }

 (void) pgstat_lock_entry(entry_ref, false);

 sharedent = (PgStatShared_Database *) entry_ref->shared_stats;
 sharedent->stats.checksum_failures += failurecount;
 sharedent->stats.last_checksum_failure = GetCurrentTimestamp();

 pgstat_unlock_entry(entry_ref);
}

/*
 * Report creation of temporary file.
 */

void
pgstat_report_tempfile(size_t filesize)
{
 PgStat_StatDBEntry *dbent;

 if (!pgstat_track_counts)
  return;

 dbent = pgstat_prep_database_pending(MyDatabaseId);
 dbent->temp_bytes += filesize;
 dbent->temp_files++;
}

/*
 * Notify stats system of a new connection.
 */

void
pgstat_report_connect(Oid dboid)
{
 PgStat_StatDBEntry *dbentry;

 if (!pgstat_should_report_connstat())
  return;

 pgLastSessionReportTime = MyStartTimestamp;

 dbentry = pgstat_prep_database_pending(dboid);
 dbentry->sessions++;
}

/*
 * Notify the stats system of a disconnect.
 */

void
pgstat_report_disconnect(Oid dboid)
{
 PgStat_StatDBEntry *dbentry;

 if (!pgstat_should_report_connstat())
  return;

 dbentry = pgstat_prep_database_pending(dboid);

 switch (pgStatSessionEndCause)
 {
  case DISCONNECT_NOT_YET:
  case DISCONNECT_NORMAL:
   /* we don't collect these */
   break;
  case DISCONNECT_CLIENT_EOF:
   dbentry->sessions_abandoned++;
   break;
  case DISCONNECT_FATAL:
   dbentry->sessions_fatal++;
   break;
  case DISCONNECT_KILLED:
   dbentry->sessions_killed++;
   break;
 }
}

/*
 * Support function for the SQL-callable pgstat* functions. Returns
 * the collected statistics for one database or NULL. NULL doesn't mean
 * that the database doesn't exist, just that there are no statistics, so the
 * caller is better off to report ZERO instead.
 */

PgStat_StatDBEntry *
pgstat_fetch_stat_dbentry(Oid dboid)
{
 return (PgStat_StatDBEntry *)
  pgstat_fetch_entry(PGSTAT_KIND_DATABASE, dboid, InvalidOid);
}

void
AtEOXact_PgStat_Database(bool isCommit, bool parallel)
{
 /* Don't count parallel worker transaction stats */
 if (!parallel)
 {
  /*
   * Count transaction commit or abort.  (We use counters, not just
   * bools, in case the reporting message isn't sent right away.)
 */

  if (isCommit)
   pgStatXactCommit++;
  else
   pgStatXactRollback++;
 }
}

/*
 * Notify the stats system about parallel worker information.
 */

void
pgstat_update_parallel_workers_stats(PgStat_Counter workers_to_launch,
          PgStat_Counter workers_launched)
{
 PgStat_StatDBEntry *dbentry;

 if (!OidIsValid(MyDatabaseId))
  return;

 dbentry = pgstat_prep_database_pending(MyDatabaseId);
 dbentry->parallel_workers_to_launch += workers_to_launch;
 dbentry->parallel_workers_launched += workers_launched;
}

/*
 * Subroutine for pgstat_report_stat(): Handle xact commit/rollback and I/O
 * timings.
 */

void
pgstat_update_dbstats(TimestampTz ts)
{
 PgStat_StatDBEntry *dbentry;

 /*
  * If not connected to a database yet, don't attribute time to "shared
  * state" (InvalidOid is used to track stats for shared relations, etc.).
 */

 if (!OidIsValid(MyDatabaseId))
  return;

 dbentry = pgstat_prep_database_pending(MyDatabaseId);

 /*
  * Accumulate xact commit/rollback and I/O timings to stats entry of the
  * current database.
 */

 dbentry->xact_commit += pgStatXactCommit;
 dbentry->xact_rollback += pgStatXactRollback;
 dbentry->blk_read_time += pgStatBlockReadTime;
 dbentry->blk_write_time += pgStatBlockWriteTime;

 if (pgstat_should_report_connstat())
 {
  long  secs;
  int   usecs;

  /*
   * pgLastSessionReportTime is initialized to MyStartTimestamp by
   * pgstat_report_connect().
 */

  TimestampDifference(pgLastSessionReportTime, ts, &secs, &usecs);
  pgLastSessionReportTime = ts;
  dbentry->session_time += (PgStat_Counter) secs * 1000000 + usecs;
  dbentry->active_time += pgStatActiveTime;
  dbentry->idle_in_transaction_time += pgStatTransactionIdleTime;
 }

 pgStatXactCommit = 0;
 pgStatXactRollback = 0;
 pgStatBlockReadTime = 0;
 pgStatBlockWriteTime = 0;
 pgStatActiveTime = 0;
 pgStatTransactionIdleTime = 0;
}

/*
 * We report session statistics only for normal backend processes.  Parallel
 * workers run in parallel, so they don't contribute to session times, even
 * though they use CPU time. Walsender processes could be considered here,
 * but they have different session characteristics from normal backends (for
 * example, they are always "active"), so they would skew session statistics.
 */

static bool
pgstat_should_report_connstat(void)
{
 return MyBackendType == B_BACKEND;
}

/*
 * Find or create a local PgStat_StatDBEntry entry for dboid.
 */

PgStat_StatDBEntry *
pgstat_prep_database_pending(Oid dboid)
{
 PgStat_EntryRef *entry_ref;

 /*
  * This should not report stats on database objects before having
  * connected to a database.
 */

 Assert(!OidIsValid(dboid) || OidIsValid(MyDatabaseId));

 entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_DATABASE, dboid, InvalidOid,
            NULL);

 return entry_ref->pending;
}

/*
 * Reset the database's reset timestamp, without resetting the contents of the
 * database stats.
 */

void
pgstat_reset_database_timestamp(Oid dboid, TimestampTz ts)
{
 PgStat_EntryRef *dbref;
 PgStatShared_Database *dbentry;

 dbref = pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE, dboid, InvalidOid,
          false);

 dbentry = (PgStatShared_Database *) dbref->shared_stats;
 dbentry->stats.stat_reset_timestamp = ts;

 pgstat_unlock_entry(dbref);
}

/*
 * Flush out pending stats for the entry
 *
 * If nowait is true and the lock could not be immediately acquired, returns
 * false without flushing the entry.  Otherwise returns true.
 */

bool
pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
{
 PgStatShared_Database *sharedent;
 PgStat_StatDBEntry *pendingent;

 pendingent = (PgStat_StatDBEntry *) entry_ref->pending;
 sharedent = (PgStatShared_Database *) entry_ref->shared_stats;

 if (!pgstat_lock_entry(entry_ref, nowait))
  return false;

#define PGSTAT_ACCUM_DBCOUNT(item)  \
 (sharedent)->stats.item += (pendingent)->item

 PGSTAT_ACCUM_DBCOUNT(xact_commit);
 PGSTAT_ACCUM_DBCOUNT(xact_rollback);
 PGSTAT_ACCUM_DBCOUNT(blocks_fetched);
 PGSTAT_ACCUM_DBCOUNT(blocks_hit);

 PGSTAT_ACCUM_DBCOUNT(tuples_returned);
 PGSTAT_ACCUM_DBCOUNT(tuples_fetched);
 PGSTAT_ACCUM_DBCOUNT(tuples_inserted);
 PGSTAT_ACCUM_DBCOUNT(tuples_updated);
 PGSTAT_ACCUM_DBCOUNT(tuples_deleted);

 /* last_autovac_time is reported immediately */
 Assert(pendingent->last_autovac_time == 0);

 PGSTAT_ACCUM_DBCOUNT(conflict_tablespace);
 PGSTAT_ACCUM_DBCOUNT(conflict_lock);
 PGSTAT_ACCUM_DBCOUNT(conflict_snapshot);
 PGSTAT_ACCUM_DBCOUNT(conflict_logicalslot);
 PGSTAT_ACCUM_DBCOUNT(conflict_bufferpin);
 PGSTAT_ACCUM_DBCOUNT(conflict_startup_deadlock);

 PGSTAT_ACCUM_DBCOUNT(temp_bytes);
 PGSTAT_ACCUM_DBCOUNT(temp_files);
 PGSTAT_ACCUM_DBCOUNT(deadlocks);

 /* checksum failures are reported immediately */
 Assert(pendingent->checksum_failures == 0);
 Assert(pendingent->last_checksum_failure == 0);

 PGSTAT_ACCUM_DBCOUNT(blk_read_time);
 PGSTAT_ACCUM_DBCOUNT(blk_write_time);

 PGSTAT_ACCUM_DBCOUNT(sessions);
 PGSTAT_ACCUM_DBCOUNT(session_time);
 PGSTAT_ACCUM_DBCOUNT(active_time);
 PGSTAT_ACCUM_DBCOUNT(idle_in_transaction_time);
 PGSTAT_ACCUM_DBCOUNT(sessions_abandoned);
 PGSTAT_ACCUM_DBCOUNT(sessions_fatal);
 PGSTAT_ACCUM_DBCOUNT(sessions_killed);
 PGSTAT_ACCUM_DBCOUNT(parallel_workers_to_launch);
 PGSTAT_ACCUM_DBCOUNT(parallel_workers_launched);
#undef PGSTAT_ACCUM_DBCOUNT

 pgstat_unlock_entry(entry_ref);

 memset(pendingent, 0sizeof(*pendingent));

 return true;
}

void
pgstat_database_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)
{
 ((PgStatShared_Database *) header)->stats.stat_reset_timestamp = ts;
}

Messung V0.5 in Prozent
C=94 H=100 G=96

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002