Optimize pg_checksums --enable where checksum is already set
authorMichael Paquier
Wed, 30 Jun 2021 00:58:59 +0000 (09:58 +0900)
committerMichael Paquier
Wed, 30 Jun 2021 00:58:59 +0000 (09:58 +0900)
This commit prevents pg_checksums to do a rewrite of a block if it has
no need to, in the case where the computed checksum matches with what's
already stored in the block read.  This is helpful to accelerate
successive runs of the tool when the previous ones got interrupted, for
example.

The number of blocks and files written is tracked and reported by the
tool once finished.  Note that the final flush of the data folder
happens even if no blocks are written, as it could be possible that a
previous interrupted run got stopped while doing a flush.

Author: Greg Sabino Mullane
Reviewed-by: Paquier Michael, Julien Rouhaud
Discussion: https://postgr.es/m/CAKAnmmL+k6goxmVzQJB+0bAR0PN1sgo6GDUXJhyhUmVMze1QAw@mail.gmail.com

doc/src/sgml/ref/pg_checksums.sgml
src/bin/pg_checksums/pg_checksums.c

index c84bc5c5b23d509768ae3066b1e39e4ec6f59a36..6a6aebed511a005761569681c306d5f2dedf5203 100644 (file)
@@ -47,7 +47,8 @@ PostgreSQL documentation
 
   
    When verifying checksums, every file in the cluster is scanned. When
-   enabling checksums, every file in the cluster is rewritten in-place.
+   enabling checksums, each relation file block with a changed checksum is 
+   rewritten in-place.
    Disabling checksums only updates the file pg_control.
   
  
index 831cf42d3ad19fcca76cdd4454f5bc98520f0f6a..3c326906e21ed610e590ae35d83b73de1c52526d 100644 (file)
 #include "storage/checksum_impl.h"
 
 
-static int64 files = 0;
-static int64 blocks = 0;
+static int64 files_scanned = 0;
+static int64 files_written = 0;
+static int64 blocks_scanned = 0;
+static int64 blocks_written = 0;
 static int64 badblocks = 0;
 static ControlFileData *ControlFile;
 
@@ -195,6 +197,7 @@ scan_file(const char *fn, BlockNumber segmentno)
    int         f;
    BlockNumber blockno;
    int         flags;
+   int64       blocks_written_in_file = 0;
 
    Assert(mode == PG_MODE_ENABLE ||
           mode == PG_MODE_CHECK);
@@ -208,7 +211,7 @@ scan_file(const char *fn, BlockNumber segmentno)
        exit(1);
    }
 
-   files++;
+   files_scanned++;
 
    for (blockno = 0;; blockno++)
    {
@@ -227,7 +230,7 @@ scan_file(const char *fn, BlockNumber segmentno)
                             blockno, fn, r, BLCKSZ);
            exit(1);
        }
-       blocks++;
+       blocks_scanned++;
 
        /*
         * Since the file size is counted as total_size for progress status
@@ -256,6 +259,15 @@ scan_file(const char *fn, BlockNumber segmentno)
        {
            int         w;
 
+           /*
+            * Do not rewrite if the checksum is already set to the expected
+            * value.
+            */
+           if (header->pd_checksum == csum)
+               continue;
+
+           blocks_written_in_file++;
+
            /* Set checksum in page header */
            header->pd_checksum = csum;
 
@@ -292,6 +304,13 @@ scan_file(const char *fn, BlockNumber segmentno)
            pg_log_info("checksums enabled in file \"%s\"", fn);
    }
 
+   /* Update write counters if any write activity has happened */
+   if (blocks_written_in_file > 0)
+   {
+       files_written++;
+       blocks_written += blocks_written_in_file;
+   }
+
    close(f);
 }
 
@@ -637,8 +656,8 @@ main(int argc, char *argv[])
            progress_report(true);
 
        printf(_("Checksum operation completed\n"));
-       printf(_("Files scanned:  %s\n"), psprintf(INT64_FORMAT, files));
-       printf(_("Blocks scanned: %s\n"), psprintf(INT64_FORMAT, blocks));
+       printf(_("Files scanned:   %s\n"), psprintf(INT64_FORMAT, files_scanned));
+       printf(_("Blocks scanned:  %s\n"), psprintf(INT64_FORMAT, blocks_scanned));
        if (mode == PG_MODE_CHECK)
        {
            printf(_("Bad checksums:  %s\n"), psprintf(INT64_FORMAT, badblocks));
@@ -647,6 +666,11 @@ main(int argc, char *argv[])
            if (badblocks > 0)
                exit(1);
        }
+       else if (mode == PG_MODE_ENABLE)
+       {
+           printf(_("Files written:  %s\n"), psprintf(INT64_FORMAT, files_written));
+           printf(_("Blocks written: %s\n"), psprintf(INT64_FORMAT, blocks_written));
+       }
    }
 
    /*