From 31f7ac9447b087099b9c0196d1087648324c989e Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Thu, 13 Aug 2026 12:15:19 +0200 Subject: [PATCH v4 2/2] 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 Co-authored-by: Daniel Gustafsson Reviewed-by: Fujii Masao Reviewed-by: Chao Li 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/pg_proc.dat | 6 +-- .../modules/test_checksums/t/001_basic.pl | 15 +++++++ 5 files changed, 73 insertions(+), 7 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} xid + + data_page_checksum_version + integer + + checkpoint_time timestamp with time zone diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml index 646076f7e39..b7a1686c135 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 by issuing the command SHOW - data_checksums. + data_checksums. + pg_control_init and + + pg_control_checkpoint can also be used for + inspecting the data checksums state at cluster initialization and current + checkpoint. Data checksums states are often referred to as data checksums + version using an integer representation due to how they were originally + implementated. contains a mapping + between state names and version, which are defined in + src/include/storage/checksum.h. + + Data Checksums States and Version Mapping + + + + State + Version + + + + + + off + 0 + + + + on + 1 + + + + inprogress-off + 2 + + + + inprogress-on + 3 + + + +
+ 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/pg_proc.dat b/src/include/catalog/pg_proc.dat index 66c3c9a04cf..1d2a9db3262 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -12432,9 +12432,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 72e0d0df46f..3b944bf334e 100644 --- a/src/test/modules/test_checksums/t/001_basic.pl +++ b/src/test/modules/test_checksums/t/001_basic.pl @@ -34,6 +34,16 @@ my $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 off. +$result = + $node->safe_psql('postgres', 'SELECT data_page_checksum_version FROM pg_control_init();'); +is($result, '0', 'ensure pg_control_init reports disabled 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); @@ -50,6 +60,11 @@ 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;"); -- 2.39.3 (Apple Git-146)