Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Add num_done counter to the pg_stat_checkpointer view.
authorFujii Masao <fujii@postgresql.org>
Mon, 30 Sep 2024 02:56:05 +0000 (11:56 +0900)
committerFujii Masao <fujii@postgresql.org>
Mon, 30 Sep 2024 02:56:05 +0000 (11:56 +0900)
Checkpoints can be skipped when the server is idle. The existing num_timed and
num_requested counters in pg_stat_checkpointer track both completed and
skipped checkpoints, but there was no way to count only the completed ones.

This commit introduces the num_done counter, which tracks only completed
checkpoints, making it easier to see how many were actually performed.

Bump catalog version.

Author: Anton A. Melnikov
Reviewed-by: Fujii Masao
Discussion: https://postgr.es/m/9ea77f40-818d-4841-9dee-158ac8f6e690@oss.nttdata.com

doc/src/sgml/monitoring.sgml
src/backend/access/transam/xlog.c
src/backend/catalog/system_views.sql
src/backend/postmaster/checkpointer.c
src/backend/utils/activity/pgstat_checkpointer.c
src/backend/utils/adt/pgstatfuncs.c
src/include/access/xlog.h
src/include/catalog/catversion.h
src/include/catalog/pg_proc.dat
src/include/pgstat.h
src/test/regress/expected/rules.out

index db7f35a45151a4dc6f2a04ff033e89eaec2280b6..d83e99da4958bf18a9b9ec460f4f0fbcc8a4cffb 100644 (file)
@@ -3063,7 +3063,16 @@ description | Waiting for a newly initialized WAL file to reach durable storage
        <structfield>num_requested</structfield> <type>bigint</type>
       </para>
       <para>
-       Number of requested checkpoints that have been performed
+       Number of backend requested checkpoints
+      </para></entry>
+     </row>
+
+      <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>num_done</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Number of checkpoints that have been performed
       </para></entry>
      </row>
 
index 853ab06812b5676fa3d938435b0cd899b9d1a672..64304d77d3778c34876796090de2af24f6cbf915 100644 (file)
@@ -6878,8 +6878,11 @@ update_checkpoint_display(int flags, bool restartpoint, bool reset)
  * In this case, we only insert an XLOG_CHECKPOINT_SHUTDOWN record, and it's
  * both the record marking the completion of the checkpoint and the location
  * from which WAL replay would begin if needed.
+ *
+ * Returns true if a new checkpoint was performed, or false if it was skipped
+ * because the system was idle.
  */
-void
+bool
 CreateCheckPoint(int flags)
 {
    bool        shutdown;
@@ -6971,7 +6974,7 @@ CreateCheckPoint(int flags)
            END_CRIT_SECTION();
            ereport(DEBUG1,
                    (errmsg_internal("checkpoint skipped because system is idle")));
-           return;
+           return false;
        }
    }
 
@@ -7353,6 +7356,8 @@ CreateCheckPoint(int flags)
                                     CheckpointStats.ckpt_segs_added,
                                     CheckpointStats.ckpt_segs_removed,
                                     CheckpointStats.ckpt_segs_recycled);
+
+   return true;
 }
 
 /*
index 7fd5d256a18cda1fd1a6949f4bdcbf607b599d77..49109dbdc86f8e47ae13a09317377b0c1e9ae649 100644 (file)
@@ -1138,6 +1138,7 @@ CREATE VIEW pg_stat_checkpointer AS
     SELECT
         pg_stat_get_checkpointer_num_timed() AS num_timed,
         pg_stat_get_checkpointer_num_requested() AS num_requested,
+        pg_stat_get_checkpointer_num_performed() AS num_done,
         pg_stat_get_checkpointer_restartpoints_timed() AS restartpoints_timed,
         pg_stat_get_checkpointer_restartpoints_requested() AS restartpoints_req,
         pg_stat_get_checkpointer_restartpoints_performed() AS restartpoints_done,
index eeb73c85726c2017a89504391b44a530d4bd1bb9..9087e3f8db13502921cb103ac4e632e411a49c7e 100644 (file)
@@ -460,10 +460,7 @@ CheckpointerMain(char *startup_data, size_t startup_data_len)
             * Do the checkpoint.
             */
            if (!do_restartpoint)
-           {
-               CreateCheckPoint(flags);
-               ckpt_performed = true;
-           }
+               ckpt_performed = CreateCheckPoint(flags);
            else
                ckpt_performed = CreateRestartPoint(flags);
 
@@ -484,7 +481,7 @@ CheckpointerMain(char *startup_data, size_t startup_data_len)
 
            ConditionVariableBroadcast(&CheckpointerShmem->done_cv);
 
-           if (ckpt_performed)
+           if (!do_restartpoint)
            {
                /*
                 * Note we record the checkpoint start time not end time as
@@ -493,18 +490,32 @@ CheckpointerMain(char *startup_data, size_t startup_data_len)
                 */
                last_checkpoint_time = now;
 
-               if (do_restartpoint)
-                   PendingCheckpointerStats.restartpoints_performed++;
+               if (ckpt_performed)
+                   PendingCheckpointerStats.num_performed++;
            }
            else
            {
-               /*
-                * We were not able to perform the restartpoint (checkpoints
-                * throw an ERROR in case of error).  Most likely because we
-                * have not received any new checkpoint WAL records since the
-                * last restartpoint. Try again in 15 s.
-                */
-               last_checkpoint_time = now - CheckPointTimeout + 15;
+               if (ckpt_performed)
+               {
+                   /*
+                    * The same as for checkpoint. Please see the
+                    * corresponding comment.
+                    */
+                   last_checkpoint_time = now;
+
+                   PendingCheckpointerStats.restartpoints_performed++;
+               }
+               else
+               {
+                   /*
+                    * We were not able to perform the restartpoint
+                    * (checkpoints throw an ERROR in case of error).  Most
+                    * likely because we have not received any new checkpoint
+                    * WAL records since the last restartpoint. Try again in
+                    * 15 s.
+                    */
+                   last_checkpoint_time = now - CheckPointTimeout + 15;
+               }
            }
 
            ckpt_active = false;
index bbfc9c7e1833c67a26efc4eb7bc76a8790fefe39..4a0a2d1493a4fc4c989901cdfa3c675744827acb 100644 (file)
@@ -49,6 +49,7 @@ pgstat_report_checkpointer(void)
 #define CHECKPOINTER_ACC(fld) stats_shmem->stats.fld += PendingCheckpointerStats.fld
    CHECKPOINTER_ACC(num_timed);
    CHECKPOINTER_ACC(num_requested);
+   CHECKPOINTER_ACC(num_performed);
    CHECKPOINTER_ACC(restartpoints_timed);
    CHECKPOINTER_ACC(restartpoints_requested);
    CHECKPOINTER_ACC(restartpoints_performed);
@@ -127,6 +128,7 @@ pgstat_checkpointer_snapshot_cb(void)
 #define CHECKPOINTER_COMP(fld) pgStatLocal.snapshot.checkpointer.fld -= reset.fld;
    CHECKPOINTER_COMP(num_timed);
    CHECKPOINTER_COMP(num_requested);
+   CHECKPOINTER_COMP(num_performed);
    CHECKPOINTER_COMP(restartpoints_timed);
    CHECKPOINTER_COMP(restartpoints_requested);
    CHECKPOINTER_COMP(restartpoints_performed);
index 9c23ac7c8c8cdeae40e0d70f948f6b0277f5a541..17b0fc02ef01ba4e7f6b1bff390ef976fbd44d88 100644 (file)
@@ -1191,6 +1191,12 @@ pg_stat_get_checkpointer_num_requested(PG_FUNCTION_ARGS)
    PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->num_requested);
 }
 
+Datum
+pg_stat_get_checkpointer_num_performed(PG_FUNCTION_ARGS)
+{
+   PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->num_performed);
+}
+
 Datum
 pg_stat_get_checkpointer_restartpoints_timed(PG_FUNCTION_ARGS)
 {
index 083810f5b4c0d89dfa6e42ffab0da94f01e15d12..36f6e4e4b4e225d2b2fb31b740de068db704579e 100644 (file)
@@ -239,7 +239,7 @@ extern void LocalProcessControlFile(bool reset);
 extern WalLevel GetActiveWalLevelOnStandby(void);
 extern void StartupXLOG(void);
 extern void ShutdownXLOG(int code, Datum arg);
-extern void CreateCheckPoint(int flags);
+extern bool CreateCheckPoint(int flags);
 extern bool CreateRestartPoint(int flags);
 extern WALAvailability GetWALAvailability(XLogRecPtr targetLSN);
 extern void XLogPutNextOid(Oid nextOid);
index ba4f8641ac6e00218336f81ccdcd503eb84e8710..7656714b701b6ccd7f52a2c02ef79530c5e7fbb4 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202409271
+#define CATALOG_VERSION_NO 202409301
 
 #endif
index 322114d72a7ce253b660a3a04340c78495afd7e8..05fcbf75156019dd6ad36ff4934b7639b2a33f78 100644 (file)
   proname => 'pg_stat_get_checkpointer_num_requested', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => '',
   prosrc => 'pg_stat_get_checkpointer_num_requested' },
+{ oid => '8599',
+  descr => 'statistics: number of checkpoints performed by the checkpointer',
+  proname => 'pg_stat_get_checkpointer_num_performed', provolatile => 's',
+  proparallel => 'r', prorettype => 'int8', proargtypes => '',
+  prosrc => 'pg_stat_get_checkpointer_num_performed' },
 { oid => '6327',
   descr => 'statistics: number of timed restartpoints started by the checkpointer',
   proname => 'pg_stat_get_checkpointer_restartpoints_timed', provolatile => 's',
index 4752dfe7197a65a3533aa393d72ae9f54afa20fc..476acd680c01f4ff368048b199d61a0fb3563909 100644 (file)
@@ -294,6 +294,7 @@ typedef struct PgStat_CheckpointerStats
 {
    PgStat_Counter num_timed;
    PgStat_Counter num_requested;
+   PgStat_Counter num_performed;
    PgStat_Counter restartpoints_timed;
    PgStat_Counter restartpoints_requested;
    PgStat_Counter restartpoints_performed;
index a1626f3fae91521988a8d44f93a7f94b2020f59f..f5434d8365c007e66099c565d3c74b40297533c2 100644 (file)
@@ -1824,6 +1824,7 @@ pg_stat_bgwriter| SELECT pg_stat_get_bgwriter_buf_written_clean() AS buffers_cle
     pg_stat_get_bgwriter_stat_reset_time() AS stats_reset;
 pg_stat_checkpointer| SELECT pg_stat_get_checkpointer_num_timed() AS num_timed,
     pg_stat_get_checkpointer_num_requested() AS num_requested,
+    pg_stat_get_checkpointer_num_performed() AS num_done,
     pg_stat_get_checkpointer_restartpoints_timed() AS restartpoints_timed,
     pg_stat_get_checkpointer_restartpoints_requested() AS restartpoints_req,
     pg_stat_get_checkpointer_restartpoints_performed() AS restartpoints_done,