Home / Alt manpages / pg_checksums(1)

  • pg_checksums(1)
  • User command
  • linux

Verify PostgreSQL Data Checksums Safely with pg_checksums

A corrupted block on disk is the failure nobody notices until a query returns garbage or a backup restore quietly fails. pg_checksums checks, enables or disables data checksums for a whole PostgreSQL cluster while it is offline. This guide targets the locally installed PostgreSQL 16.15 tool on Ubuntu and takes roughly 10 minutes for a small cluster, plus scan time.

Before you start

  • You need: the cluster data directory, access to the account that owns it, and a maintenance window.
  • The server must be stopped. pg_checksums needs a clean shutdown first; the executable is commonly under /usr/lib/postgresql/16/bin/pg_checksums, but use the path your package installed.
  • Scope is the whole cluster, not one database or table. Checking scans every file. Enabling rewrites relation-file blocks in place, so budget time and disk I/O.
  • Nothing else may write to the data directory, including PostgreSQL itself, until an enable or disable operation has finished.

Checkpoint

Have the exact data directory ready, and confirm the service is stopped. Replace /var/lib/postgresql/16/main below with your real path.

PGDATA=/var/lib/postgresql/16/main
PGCHECKSUMS=/usr/lib/postgresql/16/bin/pg_checksums

$PGCHECKSUMS --version
test -f "$PGDATA/PG_VERSION" && echo "cluster directory found"
sudo systemctl is-active postgresql

Expected version output on this machine is:

pg_checksums (PostgreSQL) 16.15 (Ubuntu 16.15-0ubuntu0.24.04.1)

The final command should report inactive before you go any further. If it reports active, stop the correct PostgreSQL instance through your normal service-management procedure. Stopping a production database is service-disrupting, so do not guess the service name or data directory.

1. Check the current checksum state

Use SQL while the server is running to read the cluster-wide setting. This is a read-only check and does not replace the offline scan:

SHOW data_checksums;

on means checksums are configured for the cluster; off means they are not. Record the result before making a change so you can recognise the intended end state.

After a clean shutdown, run the default check explicitly with --check and show progress:

sudo -u postgres "$PGCHECKSUMS" --check --progress --pgdata="$PGDATA"
printf 'exit status: %s\n' "$?"

A successful scan exits with status 0 and reports no checksum failures. A non-zero status means the scan found at least one checksum failure, or that the operation could not run. Keep the complete output and investigate before treating the cluster as healthy. This checks the whole cluster unless you deliberately use the filenode filter from step 4.

2. Enable checksums

Only do this after confirming the cluster is stopped and checksums are currently off. Enabling rewrites relation files in place and can take a long time on a large cluster.

sudo -u postgres "$PGCHECKSUMS" --enable --progress --pgdata="$PGDATA"
enable_status=$?
printf 'enable exit status: %s\n' "$enable_status"

A zero status means the operation completed. A non-zero status means it failed; do not start the server just because the command returned. If the process is aborted or killed, the checksum configuration is unchanged and you can run the same operation again.

Once the command succeeds, start PostgreSQL through your usual service procedure, then verify:

SHOW data_checksums;

Expect on. Stop the server again before any later offline check or change.

3. Disable checksums only with a rollback plan

Disabling is also a cluster-wide offline change. It updates pg_control rather than rewriting every relation block, but it removes checksum protection for future reads. Treat this as a deliberate compatibility or recovery decision, not a routine troubleshooting switch.

sudo -u postgres "$PGCHECKSUMS" --disable --progress --pgdata="$PGDATA"

After a zero exit status, start the server and confirm SHOW data_checksums; returns off.

Recovery

To undo this, stop the cluster cleanly and run the enable command again. That re-enables checksums by rewriting the required relation-file blocks.

4. Use narrow checks and safe defaults

  • --filenode=FILENODE limits validation to the relation with that filenode. Use it only when you already have a verified filenode from PostgreSQL diagnostics; it is not a substitute for the full-cluster check.
  • Skip --no-sync in production. It returns before changes are safely written, so a later operating-system crash can corrupt the data directory. It has no effect with --check anyway; the normal synchronous behaviour is the safer default.
  • --verbose lists checked files and --progress reports progress. Neither changes the checksum decision.
  • PGDATA in the environment supplies the directory when no --pgdata argument is given, but an explicit path makes a maintenance command easier to audit.
sudo -u postgres "$PGCHECKSUMS" --check --filenode=12345 --pgdata="$PGDATA"

5. Keep replication clusters in step

Warning

In a replication setup, keep the checksum setting consistent across every cluster when using tools that copy relation-file blocks directly, such as pg_rewind. An inconsistent switch can produce pages with incorrect checksums. Stop all clusters before switching them consistently; rebuilding standbys from the changed primary is the safest clean reset when your recovery plan allows it.

Done means

  • Clean shutdown confirmed for every offline command.
  • Full --check scan returned status 0, or any reported failure is under investigation.
  • SHOW data_checksums; matches the intended cluster state after a controlled restart.
  • No process wrote to the data directory during enable or disable.
  • Replication peers, backups and recovery procedures reflect the same checksum decision.