postgres.git / summary / log / commit / refs

commit    397f0fd06edc3a5b114449164c5d39c59a468b61
Author:   Daniel Gustafsson <dgustafsson@postgresql.org>
Date:     Tue Aug 18 20:25:49 2026 +0000

    Add data_page_checksum_version to pg_control_checkpoint
    
    Commit f19c0eccae added the data_checksum_version to the pg_controldata
    output, but omitted a corresponding change to the pg_control_checkpoint
    SQL function, which reports the same checkpoint information.  The field
    is named to match what pg_control_init already reports for consistency.
    
    The integer version reported is an implementation detail which bleeds
    through, but it is quite widely used and a more holistic approach to
    improving this is left as an excercise for the next major version. The
    mapping between states and versions is added to the documentation to
    make it easier for users.
    
    Backpatch to v19 where online checksums were introduced.
    
    Author: Ian Barwick <barwick@gmail.com>
    Co-authored-by: Daniel Gustafsson <daniel@yesql.se>
    Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
    Reviewed-by: Chao Li <li.evan.chao@gmail.com>
    Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
    Discussion: https://postgr.es/m/CAB8KJ=hb765sE8bKC-6sh=Yp3sCjN8xs474yuBrkwyoTM2pgZA@mail.gmail.com
    Backpatch-through: 19


doc/src/sgml/func/func-info.sgml | 5 +++ doc/src/sgml/wal.sgml | 45 +++++++++++++++++++++++- src/backend/utils/misc/pg_controldata.c | 9 +++-- src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_proc.dat | 6 ++-- src/test/modules/test_checksums/t/001_basic.pl | 18 ++++++++++ src/test/modules/test_checksums/t/004_offline.pl | 12 +++++++ 7 files changed, 89 insertions(+), 8 deletions(-) diff --git a/doc/src/sgml/func/func-info.sgml b/doc/src/sgml/func/func-info.sgml index 122fc740f1a..e3c05e8b933 100644 --- a/doc/src/sgml/func/func-info.sgml +++ b/doc/src/sgml/func/func-info.sgml @@ -3496,6 +3496,11 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres} <entry><type>xid</type></entry> </row> + <row> + <entry><structfield>data_page_checksum_version</structfield></entry> + <entry><type>integer</type></entry> + </row> + <row> <entry><structfield>checkpoint_time</structfield></entry> <entry><type>timestamp with time zone</type></entry> diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml index 646076f7e39..ec62d17fbcc 100644 --- a/doc/src/sgml/wal.sgml +++ b/doc/src/sgml/wal.sgml @@ -256,9 +256,52 @@ The current state of checksums in the cluster can be verified by viewing the value of the read-only configuration variable <xref linkend="guc-data-checksums" /> by issuing the command <command>SHOW - data_checksums</command>. + data_checksums</command>. <link linkend="functions-pg-control-init"> + <literal>pg_control_init</literal></link> and + <link linkend="functions-pg-control-checkpoint"> + <literal>pg_control_checkpoint</literal></link> can also be used for + inspecting the data checksum state at cluster initialization and current + checkpoint. Data checksum states are often referred to as data checksum + versions using an integer representation due to how they were originally + implemented. <xref linkend="data-checksums-mapping" /> contains a mapping + between state names and versions, which are defined in + <filename>src/include/storage/checksum.h</filename>. </para> + <table id="data-checksums-mapping"> + <title>Data Checksums States and Version Mapping</title> + <tgroup cols="2"> + <thead> + <row> + <entry>State</entry> + <entry>Version</entry> + </row> + </thead> + + <tbody> + <row> + <entry>off</entry> + <entry>0</entry> + </row> + + <row> + <entry>on</entry> + <entry>1</entry> + </row> + + <row> + <entry>inprogress-off</entry> + <entry>2</entry> + </row> + + <row> + <entry>inprogress-on</entry> + <entry>3</entry> + </row> + </tbody> + </tgroup> + </table> + <para> When attempting to recover from page corruptions, it may be necessary to bypass the checksum protection. To do this, temporarily set the diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c index d4feec95b26..ab74d169c96 100644 --- a/src/backend/utils/misc/pg_controldata.c +++ b/src/backend/utils/misc/pg_controldata.c @@ -69,8 +69,8 @@ pg_control_system(PG_FUNCTION_ARGS) Datum pg_control_checkpoint(PG_FUNCTION_ARGS) { - Datum values[19]; - bool nulls[19]; + Datum values[20]; + bool nulls[20]; TupleDesc tupdesc; HeapTuple htup; ControlFileData *ControlFile; @@ -154,9 +154,12 @@ pg_control_checkpoint(PG_FUNCTION_ARGS) values[17] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid); nulls[17] = false; - values[18] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time)); + values[18] = Int32GetDatum(ControlFile->checkPointCopy.dataChecksumState); nulls[18] = false; + values[19] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time)); + nulls[19] = false; + htup = heap_form_tuple(tupdesc, values, nulls); PG_RETURN_DATUM(HeapTupleGetDatum(htup)); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 80c2070f358..8b5dd160cdf 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202607272 +#define CATALOG_VERSION_NO 202608182 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index aa5ac43aff0..f5867349d14 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -12346,9 +12346,9 @@ descr => 'pg_controldata checkpoint state information as a function', proname => 'pg_control_checkpoint', provolatile => 'v', prorettype => 'record', proargtypes => '', - proallargtypes => '{pg_lsn,pg_lsn,text,int4,int4,bool,bool,text,oid,xid,xid,xid,oid,xid,xid,oid,xid,xid,timestamptz}', - proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', - proargnames => '{checkpoint_lsn,redo_lsn,redo_wal_file,timeline_id,prev_timeline_id,full_page_writes,logical_decoding,next_xid,next_oid,next_multixact_id,next_multi_offset,oldest_xid,oldest_xid_dbid,oldest_active_xid,oldest_multi_xid,oldest_multi_dbid,oldest_commit_ts_xid,newest_commit_ts_xid,checkpoint_time}', + proallargtypes => '{pg_lsn,pg_lsn,text,int4,int4,bool,bool,text,oid,xid,xid,xid,oid,xid,xid,oid,xid,xid,int4,timestamptz}', + proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{checkpoint_lsn,redo_lsn,redo_wal_file,timeline_id,prev_timeline_id,full_page_writes,logical_decoding,next_xid,next_oid,next_multixact_id,next_multi_offset,oldest_xid,oldest_xid_dbid,oldest_active_xid,oldest_multi_xid,oldest_multi_dbid,oldest_commit_ts_xid,newest_commit_ts_xid,data_page_checksum_version,checkpoint_time}', prosrc => 'pg_control_checkpoint' }, { oid => '3443', diff --git a/src/test/modules/test_checksums/t/001_basic.pl b/src/test/modules/test_checksums/t/001_basic.pl index 7477f00947d..5a16b6fb9e4 100644 --- a/src/test/modules/test_checksums/t/001_basic.pl +++ b/src/test/modules/test_checksums/t/001_basic.pl @@ -43,6 +43,18 @@ enable_data_checksums($node, wait => 'on'); $result = $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1 "); is($result, '9999', 'ensure checksummed pages can be read back'); +# Ensure the new state is registered properly in pg_control_checkpoint() +$result = + $node->safe_psql('postgres', + 'SELECT data_page_checksum_version FROM pg_control_checkpoint();'); +is($result, '1', 'ensure pg_control_checkpoint reports enabled state'); +# Regardless of the new state, pg_control_init() should still report checksums +# as on. +$result = + $node->safe_psql('postgres', + 'SELECT data_page_checksum_version FROM pg_control_init();'); +is($result, '1', 'ensure pg_control_init reports enabled state'); + # Enable data checksums again which should be a no-op so we explicitly don't # wait for any state transition as none should happen here. enable_data_checksums($node); @@ -59,6 +71,12 @@ disable_data_checksums($node, wait => 1); $result = $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1"); is($result, '10000', 'ensure previously checksummed pages can be read back'); +# And ensure the disabled state is shown in pg_control_checkpoint() +$result = + $node->safe_psql('postgres', + 'SELECT data_page_checksum_version FROM pg_control_checkpoint();'); +is($result, '0', 'ensure pg_control_checkpoint reports disabled state'); + # Re-enable checksums and make sure that the underlying data has changed to # ensure that checksums will be different. $node->safe_psql('postgres', "UPDATE t SET a = a + 1;"); diff --git a/src/test/modules/test_checksums/t/004_offline.pl b/src/test/modules/test_checksums/t/004_offline.pl index 48254111410..d0eee3afe46 100644 --- a/src/test/modules/test_checksums/t/004_offline.pl +++ b/src/test/modules/test_checksums/t/004_offline.pl @@ -40,6 +40,18 @@ $node->start; # Ensure that checksums are enabled test_checksum_state($node, 'on'); +# Since offline checksums don't issue a checkpoint like online checksums, the +# first call to pg_control_checkpoint will show the state as off even though +# checksums are enabled. After a CHECKPOINT, pg_control_checkpoint shall +# return 1. +$result = $node->safe_psql('postgres', + 'SELECT data_page_checksum_version FROM pg_control_checkpoint();'); +is($result, '0', 'latest checkpoint will still see off state'); +$node->safe_psql('postgres', 'CHECKPOINT;'); +$result = $node->safe_psql('postgres', + 'SELECT data_page_checksum_version FROM pg_control_checkpoint();'); +is($result, '1', 'latest checkpoint will now see on state'); + # Make sure pg_control_init still reports the initial state as disabled even # though the current state has changed. $result = $node->safe_psql('postgres', [parent: aaf8b9989f7a]