public inbox for [email protected]
help / color / mirror / Atom feed[PATCH 1/2] Move tablespace cleanup out of pg_regress.
8+ messages / 4 participants
[nested] [flat]
* [PATCH 1/2] Move tablespace cleanup out of pg_regress.
@ 2020-04-30 05:06 Kyotaro Horiguchi <[email protected]>
0 siblings, 0 replies; 8+ messages in thread
From: Kyotaro Horiguchi @ 2020-04-30 05:06 UTC (permalink / raw)
Tablespace directory is cleaned-up in regress/GNUmakefile for all
platforms other than Windows. For Windoiws pg_regress does that on
behalf of make, which is ugly. In addition to that, pg_regress does
the clean up twice at once. This patch moves the cleanup code out of
pg_regress into vcregress.pl, which is more sutable place.
---
src/test/regress/pg_regress.c | 22 ----------------------
src/tools/msvc/vcregress.pl | 14 ++++++++++++++
2 files changed, 14 insertions(+), 22 deletions(-)
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index 38b2b1e8e1..c56bfaf7f5 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -491,28 +491,6 @@ convert_sourcefiles_in(const char *source_subdir, const char *dest_dir, const ch
snprintf(testtablespace, MAXPGPATH, "%s/testtablespace", outputdir);
-#ifdef WIN32
-
- /*
- * On Windows only, clean out the test tablespace dir, or create it if it
- * doesn't exist. On other platforms we expect the Makefile to take care
- * of that. (We don't migrate that functionality in here because it'd be
- * harder to cope with platform-specific issues such as SELinux.)
- *
- * XXX it would be better if pg_regress.c had nothing at all to do with
- * testtablespace, and this were handled by a .BAT file or similar on
- * Windows. See pgsql-hackers discussion of 2008-01-18.
- */
- if (directory_exists(testtablespace))
- if (!rmtree(testtablespace, true))
- {
- fprintf(stderr, _("\n%s: could not remove test tablespace \"%s\"\n"),
- progname, testtablespace);
- exit(2);
- }
- make_directory(testtablespace);
-#endif
-
/* finally loop on each file and do the replacement */
for (name = names; *name; name++)
{
diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl
index f95f7a5c7a..74d37a31de 100644
--- a/src/tools/msvc/vcregress.pl
+++ b/src/tools/msvc/vcregress.pl
@@ -104,6 +104,7 @@ exit 0;
sub installcheck_internal
{
my ($schedule, @EXTRA_REGRESS_OPTS) = @_;
+
my @args = (
"../../../$Config/pg_regress/pg_regress",
"--dlpath=.",
@@ -114,6 +115,7 @@ sub installcheck_internal
"--no-locale");
push(@args, $maxconn) if $maxconn;
push(@args, @EXTRA_REGRESS_OPTS);
+ CleanupTablespaceDirectory();
system(@args);
my $status = $? >> 8;
exit $status if $status;
@@ -143,6 +145,7 @@ sub check
"--temp-instance=./tmp_check");
push(@args, $maxconn) if $maxconn;
push(@args, $temp_config) if $temp_config;
+ CleanupTablespaceDirectory();
system(@args);
my $status = $? >> 8;
exit $status if $status;
@@ -178,6 +181,7 @@ sub ecpgcheck
sub isolationcheck
{
chdir "../isolation";
+ CleanupTablespaceDirectory();
copy("../../../$Config/isolationtester/isolationtester.exe",
"../../../$Config/pg_isolation_regress");
my @args = (
@@ -382,6 +386,7 @@ sub plcheck
"$topdir/$Config/pg_regress/pg_regress",
"--bindir=$topdir/$Config/psql",
"--dbname=pl_regression", @lang_args, @tests);
+ CleanupTablespaceDirectory();
system(@args);
my $status = $? >> 8;
exit $status if $status;
@@ -439,6 +444,7 @@ sub subdircheck
print "============================================================\n";
print "Checking $module\n";
+ CleanupTablespaceDirectory();
my @args = (
"$topdir/$Config/pg_regress/pg_regress",
"--bindir=${topdir}/${Config}/psql",
@@ -741,6 +747,14 @@ sub InstallTemp
return;
}
+sub CleanupTablespaceDirectory
+{
+ my $tablespace = 'testtablespace';
+
+ rmtree($tablespace) if (-e $tablespace);
+ mkdir($tablespace);
+}
+
sub usage
{
print STDERR
--
2.18.2
----Next_Part(Mon_May_11_17_13_54_2020_626)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="0002-Don-t-setup-tablespace-directory-while-testing-pg_up.patch"
^ permalink raw reply [nested|flat] 8+ messages in thread
* allow spread checkpoints when changing checksums online
@ 2026-05-04 13:42 Tomas Vondra <[email protected]>
0 siblings, 1 reply; 8+ messages in thread
From: Tomas Vondra @ 2026-05-04 13:42 UTC (permalink / raw)
To: pgsql-hackers
Hi,
Here's a small patch re-introducing the option to use spread checkpoints
(instead of always using CHECKPOINT_FAST) for online checksum changes.
The version v20251201 posted in [1] supported this, but the next patch
version was without checkpoints and so removed the "fast" parameter too.
Then we realized the checkpoints are actually needed, but were added
back to keep it as simple as possible. Or maybe it was an omission, not
sure, and there's no explanation on the thread.
I recall someone claiming always doing fast checkpoints is fine, because
we've already written the whole database into WAL anyway, and on large
databases that's likely way more expensive than a single checkpoint. I
don't buy that, for two reasons:
- We do have throttling for the rewrite phase, thanks to the cost_limit
and cost_delay parameters. So we can effectively throttle it, to reduce
impact of the checksums change. In which case the "fast" checkpoint can
be way more disruptive.
- We need to do checkpoints even when "disabling" checksums, in which
case we don't rewrite any data pages (or WAL-log anything), we just need
to persist the new checksum state. Which just makes the fast checkpoint
relatively more disruptive.
The attached patch is mostly extracted from v20251201, and adds the
"fast" parameter back to pg_{enable,disable}_data_checksums.
I have two open questions regarding it:
1) What should be the default? I've used fast=true, mostly because
that's what PG19 is going to do (fast checkpoints by default). It's also
somewhat consistent with e.g. VACUUM which does no throttling by
default. But I assume most production uses would want fast=false?
2) I haven't adjusted the TAP tests. We could use fast=false in a couple
of the test_checksums tests, but I'm not sure it's worth it and it makes
it way more time consuming.
We could reduce checkpoint_timeout to something very aggressive. And in
fact that's what I did locally with the TAP tests I posted in [2]. But
I'm still not convinced it's worth it - the checkpoints are still
synchronous, of course.
regards
[1]
https://www.postgresql.org/message-id/477897AE-1314-4724-9694-0BABC4F4ABDA%40yesql.se
[2]
https://www.postgresql.org/message-id/9e1331e1-93a0-4e27-934a-17b89342be4d%40vondra.me
--
Tomas Vondra
Attachments:
[text/x-patch] 0001-add-fast-parameter-to-enable-disable-checksums.patch (12.6K, ../../[email protected]/2-0001-add-fast-parameter-to-enable-disable-checksums.patch)
download | inline diff:
From 4eba7bbb739f5e7b95c4909d1cee2a437d8c6eb3 Mon Sep 17 00:00:00 2001
From: test <test>
Date: Sun, 3 May 2026 00:40:17 +0200
Subject: [PATCH 1/2] add fast parameter to enable/disable checksums
XXX Should this default to true or false? Most production systems would
probably want 'false' to reduce impact, but PG19 does fast checkpoints
by default.
---
doc/src/sgml/func/func-admin.sgml | 14 ++++++++++--
src/backend/access/transam/xlog.c | 23 ++++++++++++++------
src/backend/postmaster/datachecksum_state.c | 24 +++++++++++++++------
src/include/access/xlog.h | 4 ++--
src/include/catalog/pg_proc.dat | 11 +++++-----
src/include/postmaster/datachecksum_state.h | 3 ++-
6 files changed, 56 insertions(+), 23 deletions(-)
diff --git a/doc/src/sgml/func/func-admin.sgml b/doc/src/sgml/func/func-admin.sgml
index 24ecb46542e..06360ea1b95 100644
--- a/doc/src/sgml/func/func-admin.sgml
+++ b/doc/src/sgml/func/func-admin.sgml
@@ -3158,7 +3158,7 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
<indexterm>
<primary>pg_enable_data_checksums</primary>
</indexterm>
- <function>pg_enable_data_checksums</function> ( <optional><parameter>cost_delay</parameter> <type>int</type>, <parameter>cost_limit</parameter> <type>int</type></optional> )
+ <function>pg_enable_data_checksums</function> ( <optional><parameter>cost_delay</parameter> <type>int</type>, <parameter>cost_limit</parameter> <type>int</type></optional>, <parameter>fast</parameter> <type>bool</type></optional> )
<returnvalue>void</returnvalue>
</para>
<para>
@@ -3175,6 +3175,11 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
specified, the process is throttled using the same principles as
<link linkend="runtime-config-resource-vacuum-cost">Cost-based Vacuum Delay</link>.
</para>
+ <para>
+ If <parameter>fast</parameter> is specified as <literal>true</literal>
+ then a fast checkpoint will be issued when data checksums have been
+ enabled, which may cause a spike in I/O.
+ </para>
</entry>
</row>
@@ -3183,7 +3188,7 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
<indexterm>
<primary>pg_disable_data_checksums</primary>
</indexterm>
- <function>pg_disable_data_checksums</function> ()
+ <function>pg_disable_data_checksums</function> ( <optional><parameter>fast</parameter> <type>bool</type></optional> )
<returnvalue>void</returnvalue>
</para>
<para>
@@ -3193,6 +3198,11 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
stopped validating data checksums, the data checksum state will be
set to <literal>off</literal>.
</para>
+ <para>
+ If <parameter>fast</parameter> is specified as <literal>true</literal>
+ then a fast checkpoint will be issued when data checksums have been
+ enabled, which may cause a spike in I/O.
+ </para>
</entry>
</row>
</tbody>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 18d5dee06e0..6b8b48fa4ce 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4803,9 +4803,10 @@ SetDataChecksumsOnInProgress(void)
* state transition.
*/
void
-SetDataChecksumsOn(void)
+SetDataChecksumsOn(bool fast)
{
uint64 barrier;
+ int flags;
SpinLockAcquire(&XLogCtl->info_lck);
@@ -4820,7 +4821,7 @@ SetDataChecksumsOn(void)
SpinLockRelease(&XLogCtl->info_lck);
elog(WARNING,
"cannot set data checksums to \"on\", current state is not \"inprogress-on\", disabling");
- SetDataChecksumsOff();
+ SetDataChecksumsOff(fast);
return;
}
@@ -4850,7 +4851,11 @@ SetDataChecksumsOn(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ flags = CHECKPOINT_FORCE | CHECKPOINT_WAIT;
+ if (fast)
+ flags |= CHECKPOINT_FAST;
+
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
}
@@ -4868,9 +4873,15 @@ SetDataChecksumsOn(void)
* state transition.
*/
void
-SetDataChecksumsOff(void)
+SetDataChecksumsOff(bool fast)
{
uint64 barrier;
+ int flags;
+
+ /* determine flags for the checkpoint(s) */
+ flags = CHECKPOINT_FORCE | CHECKPOINT_WAIT;
+ if (fast)
+ flags |= CHECKPOINT_FAST;
SpinLockAcquire(&XLogCtl->info_lck);
@@ -4912,7 +4923,7 @@ SetDataChecksumsOff(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
/*
@@ -4950,7 +4961,7 @@ SetDataChecksumsOff(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
}
diff --git a/src/backend/postmaster/datachecksum_state.c b/src/backend/postmaster/datachecksum_state.c
index d0d6acdd6a2..286096217d9 100644
--- a/src/backend/postmaster/datachecksum_state.c
+++ b/src/backend/postmaster/datachecksum_state.c
@@ -291,6 +291,7 @@ typedef struct DataChecksumsStateStruct
DataChecksumsWorkerOperation launch_operation;
int launch_cost_delay;
int launch_cost_limit;
+ bool launch_fast_checkpoint;
/*
* Is a launcher process currently running? This is set by the main
@@ -318,6 +319,7 @@ typedef struct DataChecksumsStateStruct
DataChecksumsWorkerOperation operation;
int cost_delay;
int cost_limit;
+ bool fast_checkpoint;
/*
* Signaling between the launcher and the worker process.
@@ -509,6 +511,8 @@ AbsorbDataChecksumsBarrier(ProcSignalBarrierType barrier)
Datum
disable_data_checksums(PG_FUNCTION_ARGS)
{
+ bool fast = PG_GETARG_BOOL(0);
+
PreventCommandDuringRecovery("pg_disable_data_checksums()");
if (!superuser())
@@ -516,7 +520,7 @@ disable_data_checksums(PG_FUNCTION_ARGS)
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to change data checksum state"));
- StartDataChecksumsWorkerLauncher(DISABLE_DATACHECKSUMS, 0, 0);
+ StartDataChecksumsWorkerLauncher(DISABLE_DATACHECKSUMS, 0, 0, fast);
PG_RETURN_VOID();
}
@@ -530,6 +534,7 @@ enable_data_checksums(PG_FUNCTION_ARGS)
{
int cost_delay = PG_GETARG_INT32(0);
int cost_limit = PG_GETARG_INT32(1);
+ bool fast = PG_GETARG_BOOL(2);
PreventCommandDuringRecovery("pg_enable_data_checksums()");
@@ -548,7 +553,7 @@ enable_data_checksums(PG_FUNCTION_ARGS)
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cost limit must be greater than zero"));
- StartDataChecksumsWorkerLauncher(ENABLE_DATACHECKSUMS, cost_delay, cost_limit);
+ StartDataChecksumsWorkerLauncher(ENABLE_DATACHECKSUMS, cost_delay, cost_limit, fast);
PG_RETURN_VOID();
}
@@ -568,7 +573,8 @@ enable_data_checksums(PG_FUNCTION_ARGS)
void
StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
int cost_delay,
- int cost_limit)
+ int cost_limit,
+ bool fast)
{
BackgroundWorker bgw;
BackgroundWorkerHandle *bgw_handle;
@@ -588,6 +594,7 @@ StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
DataChecksumState->launch_operation = op;
DataChecksumState->launch_cost_delay = cost_delay;
DataChecksumState->launch_cost_limit = cost_limit;
+ DataChecksumState->launch_fast_checkpoint = fast;
/* Is the launcher already running? If so, what is it doing? */
running = DataChecksumState->launcher_running;
@@ -938,7 +945,7 @@ launcher_exit(int code, Datum arg)
* the state to off since processing cannot be resumed.
*/
if (DataChecksumsInProgressOn())
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
launcher_running = false;
@@ -1081,6 +1088,7 @@ DataChecksumsWorkerLauncherMain(Datum arg)
DataChecksumState->operation = operation;
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
LWLockRelease(DataChecksumsWorkerLock);
/*
@@ -1139,7 +1147,7 @@ again:
* Data checksums have been set on all pages, set the state to on in
* order to instruct backends to validate checksums on reading.
*/
- SetDataChecksumsOn();
+ SetDataChecksumsOn(DataChecksumState->fast_checkpoint);
ereport(LOG,
errmsg("data checksums are now enabled"));
@@ -1151,7 +1159,7 @@ again:
pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_PHASE,
PROGRESS_DATACHECKSUMS_PHASE_DISABLING);
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
ereport(LOG,
errmsg("data checksums are now disabled"));
}
@@ -1179,6 +1187,7 @@ done:
operation = DataChecksumState->launch_operation;
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
LWLockRelease(DataChecksumsWorkerLock);
goto again;
}
@@ -1268,7 +1277,7 @@ ProcessAllDatabases(void)
* Disable checksums on cluster, because we failed one of the
* databases and this is an all or nothing process.
*/
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
ereport(ERROR,
errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("data checksums failed to get enabled in all databases, aborting"),
@@ -1606,6 +1615,7 @@ DataChecksumsWorkerMain(Datum arg)
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
}
else
costs_updated = false;
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 4dd98624204..8a9e8961a6a 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -253,8 +253,8 @@ extern bool DataChecksumsOn(void);
extern bool DataChecksumsOff(void);
extern bool DataChecksumsInProgressOn(void);
extern void SetDataChecksumsOnInProgress(void);
-extern void SetDataChecksumsOn(void);
-extern void SetDataChecksumsOff(void);
+extern void SetDataChecksumsOn(bool fast);
+extern void SetDataChecksumsOff(bool fast);
extern const char *show_data_checksums(void);
extern const char *get_checksum_state_string(uint32 state);
extern void InitLocalDataChecksumState(void);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index fa9ae79082b..fed5fba4c0c 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12457,14 +12457,15 @@
{ oid => '9258',
descr => 'disable data checksums',
proname => 'pg_disable_data_checksums', provolatile => 'v', prorettype => 'void',
- proparallel => 'r', prosrc => 'disable_data_checksums', proargtypes => '',
- proacl => '{POSTGRES=X}'},
+ proparallel => 'r', prosrc => 'disable_data_checksums', proargtypes => 'bool',
+ proallargtypes => '{bool}', proargmodes => '{i}', proargnames => '{fast}',
+ proargdefaults => '{true}', proacl => '{POSTGRES=X}'},
{ oid => '9257',
descr => 'enable data checksums',
proname => 'pg_enable_data_checksums', provolatile => 'v', prorettype => 'void',
- proparallel => 'r', proargtypes => 'int4 int4', proallargtypes => '{int4,int4}',
- proargmodes => '{i,i}', proargnames => '{cost_delay,cost_limit}',
- proargdefaults => '{0,100}', prosrc => 'enable_data_checksums',
+ proparallel => 'r', proargtypes => 'int4 int4 bool', proallargtypes => '{int4,int4,bool}',
+ proargmodes => '{i,i,i}', proargnames => '{cost_delay,cost_limit,fast}',
+ proargdefaults => '{0,100,true}', prosrc => 'enable_data_checksums',
proacl => '{POSTGRES=X}'},
# collation management functions
diff --git a/src/include/postmaster/datachecksum_state.h b/src/include/postmaster/datachecksum_state.h
index 2a1ae10d55d..6bd975c0670 100644
--- a/src/include/postmaster/datachecksum_state.h
+++ b/src/include/postmaster/datachecksum_state.h
@@ -45,7 +45,8 @@ void EmitAndWaitDataChecksumsBarrier(uint32 state);
/* Start the background processes for enabling or disabling checksums */
void StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
int cost_delay,
- int cost_limit);
+ int cost_limit,
+ bool fast);
/* Background worker entrypoints */
void DataChecksumsWorkerLauncherMain(Datum arg);
--
2.54.0
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: allow spread checkpoints when changing checksums online
@ 2026-07-06 11:43 Tomas Vondra <[email protected]>
parent: Tomas Vondra <[email protected]>
0 siblings, 1 reply; 8+ messages in thread
From: Tomas Vondra @ 2026-07-06 11:43 UTC (permalink / raw)
To: pgsql-hackers
Hi,
Here's a rebased patch, addressing the minor bitrot, and with some very
minor adjustments.
1) proper commit message
2) cleanup / rewording in the sgml docs
3) I've noticed the SGML docs don't have default values for the existing
parameters (cost_delay, cost_limit), so I added those. Maybe backpatch?
4) I've added the new 'fast' parameter to the DataChecksums module, but
mostly just for completeness. The TAP tests still use the default value,
so that it doesn't take longer.
I've spent some time thinking about the default value. For a while I
thought maybe it should default to 'false' (in which case we use spread
checkpoints, which is the less disruptive option).
But that's actually futile, because the cost_delay still defaults to 0,
which means the "data page rewrite" phase won't be paced. It seems
surprising the first phase would not be throttled by default, while the
checkpoints are ...
So I ended up setting the 'fast=true' default.
This is not a very complicated patch, and it's been part of the old
patch series for quite a while. So unless there's some objections I'll
get this committed in a couple days.
regards
--
Tomas Vondra
Attachments:
[text/x-patch] v2-0001-Allow-using-spread-checkpoints-when-enabling-disa.patch (15.9K, ../../[email protected]/2-v2-0001-Allow-using-spread-checkpoints-when-enabling-disa.patch)
download | inline diff:
From 7a356fe8ec1c54e5976549b1c9e78bb9af81a705 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <[email protected]>
Date: Mon, 6 Jul 2026 11:31:19 +0200
Subject: [PATCH v2] Allow using spread checkpoints when enabling/disabling
checksums
This commit allows using spread (throttled) checkpoints while enabling
or disabling data checksums in a running cluster, to limit the impact on
the rest of the system.
While enabling checksums, the process has to rewrite all data pages, and
then perform perform checkpoints at certain points. It was possible to
throttle the rewriting of data pages, to limit the impact on the rest of
the cluster, the ckeckpoints were always issued as CHECKPOINT_FAST. This
can be very disruptive.
When disabling checksums, it's not necessary to rewrite any data pages,
but the checkpoint may still trigger a lot of I/O. So a seemingly cheap
operation (disabling checksums) may get rather disruptive.
This commit introduces a new "fast" parameter for functions initiating
the checksum state change. The default "fast=true" means the requested
checkpoints are fast.
---
doc/src/sgml/func/func-admin.sgml | 22 +++++++++++++--
src/backend/access/transam/xlog.c | 24 ++++++++++++-----
src/backend/postmaster/datachecksum_state.c | 27 +++++++++++++------
src/include/access/xlog.h | 4 +--
src/include/catalog/pg_proc.dat | 12 +++++----
.../test_checksums/t/DataChecksums/Utils.pm | 24 ++++++++++++++---
6 files changed, 87 insertions(+), 26 deletions(-)
diff --git a/doc/src/sgml/func/func-admin.sgml b/doc/src/sgml/func/func-admin.sgml
index 0eae1c1f616..97b768638c5 100644
--- a/doc/src/sgml/func/func-admin.sgml
+++ b/doc/src/sgml/func/func-admin.sgml
@@ -3158,7 +3158,7 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
<indexterm>
<primary>pg_enable_data_checksums</primary>
</indexterm>
- <function>pg_enable_data_checksums</function> ( <optional><parameter>cost_delay</parameter> <type>int</type>, <parameter>cost_limit</parameter> <type>int</type></optional> )
+ <function>pg_enable_data_checksums</function> ( <optional><parameter>cost_delay</parameter> <type>int</type> <literal>DEFAULT</literal> <literal>0</literal>, <parameter>cost_limit</parameter> <type>int</type> <literal>DEFAULT</literal> <literal>100</literal>, <parameter>fast</parameter> <type>bool</type> <literal>DEFAULT</literal> <literal>true</literal></optional> )
<returnvalue>void</returnvalue>
</para>
<para>
@@ -3175,6 +3175,15 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
specified, the process is throttled using the same principles as
<link linkend="runtime-config-resource-vacuum-cost">Cost-based Vacuum Delay</link>.
</para>
+ <para>
+ The <parameter>fast</parameter> specifies whether the checkpoints performed
+ are fast or spread.
+ When set to <literal>true</literal> the checkpoints are fast, which may cause
+ a spike in I/O. When set to <literal>false</literal>, the checkpoints are
+ spread (throttled), which may increase the time needed to enable checksums,
+ but it limits the impact on the system.
+ The default value is <literal>true</literal>.
+ </para>
</entry>
</row>
@@ -3183,7 +3192,7 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
<indexterm>
<primary>pg_disable_data_checksums</primary>
</indexterm>
- <function>pg_disable_data_checksums</function> ()
+ <function>pg_disable_data_checksums</function> ( <optional><parameter>fast</parameter> <type>bool</type> <literal>DEFAULT</literal> <literal>false</literal></optional> )
<returnvalue>void</returnvalue>
</para>
<para>
@@ -3193,6 +3202,15 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
stopped validating data checksums, the data checksum state will be
set to <literal>off</literal>.
</para>
+ <para>
+ The <parameter>fast</parameter> specifies whether the checkpoints performed
+ are fast or spread.
+ When set to <literal>true</literal> the checkpoints are fast, which may cause
+ a spike in I/O. When set to <literal>false</literal>, the checkpoints are
+ spread (throttled), which may increase the time needed to disable checksums,
+ but it limits the impact on the system.
+ The default value is <literal>true</literal>.
+ </para>
</entry>
</row>
</tbody>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index a81912b7441..aaca0437a5f 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4799,9 +4799,10 @@ SetDataChecksumsOnInProgress(void)
* state transition.
*/
void
-SetDataChecksumsOn(void)
+SetDataChecksumsOn(bool fast)
{
uint64 barrier;
+ int flags;
SpinLockAcquire(&XLogCtl->info_lck);
@@ -4815,7 +4816,7 @@ SetDataChecksumsOn(void)
SpinLockRelease(&XLogCtl->info_lck);
elog(WARNING,
"cannot set data checksums to \"on\", current state is not \"inprogress-on\", disabling");
- SetDataChecksumsOff();
+ SetDataChecksumsOff(fast);
return;
}
@@ -4845,7 +4846,12 @@ SetDataChecksumsOn(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ /* determine flags for the checkpoint */
+ flags = CHECKPOINT_FORCE | CHECKPOINT_WAIT;
+ if (fast)
+ flags |= CHECKPOINT_FAST;
+
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
}
@@ -4863,9 +4869,15 @@ SetDataChecksumsOn(void)
* state transition.
*/
void
-SetDataChecksumsOff(void)
+SetDataChecksumsOff(bool fast)
{
uint64 barrier;
+ int flags;
+
+ /* determine flags for the checkpoint(s) */
+ flags = CHECKPOINT_FORCE | CHECKPOINT_WAIT;
+ if (fast)
+ flags |= CHECKPOINT_FAST;
SpinLockAcquire(&XLogCtl->info_lck);
@@ -4907,7 +4919,7 @@ SetDataChecksumsOff(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
/*
@@ -4945,7 +4957,7 @@ SetDataChecksumsOff(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
}
diff --git a/src/backend/postmaster/datachecksum_state.c b/src/backend/postmaster/datachecksum_state.c
index 68557c16cb9..7519d44571e 100644
--- a/src/backend/postmaster/datachecksum_state.c
+++ b/src/backend/postmaster/datachecksum_state.c
@@ -307,6 +307,7 @@ typedef struct DataChecksumsStateStruct
DataChecksumsWorkerOperation launch_operation;
int launch_cost_delay;
int launch_cost_limit;
+ bool launch_fast_checkpoint;
/*
* Is a launcher process currently running? This is set by the main
@@ -340,6 +341,7 @@ typedef struct DataChecksumsStateStruct
DataChecksumsWorkerOperation operation;
int cost_delay;
int cost_limit;
+ bool fast_checkpoint;
/*
* Signaling between the launcher and the worker process. Protected by
@@ -382,7 +384,8 @@ static DataChecksumsWorkerOperation operation;
/* Prototypes */
static void StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
int cost_delay,
- int cost_limit);
+ int cost_limit,
+ bool fast);
static void DataChecksumsShmemRequest(void *arg);
static bool DatabaseExists(Oid dboid);
static List *BuildDatabaseList(void);
@@ -543,6 +546,8 @@ AbsorbDataChecksumsBarrier(ProcSignalBarrierType barrier)
Datum
disable_data_checksums(PG_FUNCTION_ARGS)
{
+ bool fast = PG_GETARG_BOOL(0);
+
PreventCommandDuringRecovery("pg_disable_data_checksums()");
if (!superuser())
@@ -550,7 +555,7 @@ disable_data_checksums(PG_FUNCTION_ARGS)
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to change data checksum state"));
- StartDataChecksumsWorkerLauncher(DISABLE_DATACHECKSUMS, 0, 0);
+ StartDataChecksumsWorkerLauncher(DISABLE_DATACHECKSUMS, 0, 0, fast);
PG_RETURN_VOID();
}
@@ -564,6 +569,7 @@ enable_data_checksums(PG_FUNCTION_ARGS)
{
int cost_delay = PG_GETARG_INT32(0);
int cost_limit = PG_GETARG_INT32(1);
+ bool fast = PG_GETARG_BOOL(2);
PreventCommandDuringRecovery("pg_enable_data_checksums()");
@@ -582,7 +588,7 @@ enable_data_checksums(PG_FUNCTION_ARGS)
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cost limit must be greater than zero"));
- StartDataChecksumsWorkerLauncher(ENABLE_DATACHECKSUMS, cost_delay, cost_limit);
+ StartDataChecksumsWorkerLauncher(ENABLE_DATACHECKSUMS, cost_delay, cost_limit, fast);
PG_RETURN_VOID();
}
@@ -602,7 +608,8 @@ enable_data_checksums(PG_FUNCTION_ARGS)
static void
StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
int cost_delay,
- int cost_limit)
+ int cost_limit,
+ bool fast)
{
BackgroundWorker bgw;
BackgroundWorkerHandle *bgw_handle;
@@ -622,6 +629,7 @@ StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
DataChecksumState->launch_operation = op;
DataChecksumState->launch_cost_delay = cost_delay;
DataChecksumState->launch_cost_limit = cost_limit;
+ DataChecksumState->launch_fast_checkpoint = fast;
/* Is the launcher already running? If so, what is it doing? */
running = DataChecksumState->launcher_running;
@@ -989,7 +997,7 @@ launcher_exit(int code, Datum arg)
* the state to off since processing cannot be resumed.
*/
if (DataChecksumsInProgressOn())
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
launcher_running = false;
@@ -1130,6 +1138,7 @@ DataChecksumsWorkerLauncherMain(Datum arg)
DataChecksumState->operation = operation;
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
LWLockRelease(DataChecksumsWorkerLock);
/*
@@ -1184,7 +1193,7 @@ again:
* Data checksums have been set on all pages, set the state to on in
* order to instruct backends to validate checksums on reading.
*/
- SetDataChecksumsOn();
+ SetDataChecksumsOn(DataChecksumState->fast_checkpoint);
ereport(LOG,
errmsg("data checksums are now enabled"));
@@ -1196,7 +1205,7 @@ again:
pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_PHASE,
PROGRESS_DATACHECKSUMS_PHASE_DISABLING);
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
ereport(LOG,
errmsg("data checksums are now disabled"));
}
@@ -1224,6 +1233,7 @@ done:
operation = DataChecksumState->launch_operation;
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
LWLockRelease(DataChecksumsWorkerLock);
goto again;
}
@@ -1313,7 +1323,7 @@ ProcessAllDatabases(void)
* Disable checksums on cluster, because we failed one of the
* databases and this is an all or nothing process.
*/
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
ereport(ERROR,
errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("data checksums failed to get enabled in all databases, aborting"),
@@ -1676,6 +1686,7 @@ DataChecksumsWorkerMain(Datum arg)
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
}
else
costs_updated = false;
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 4dd98624204..8a9e8961a6a 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -253,8 +253,8 @@ extern bool DataChecksumsOn(void);
extern bool DataChecksumsOff(void);
extern bool DataChecksumsInProgressOn(void);
extern void SetDataChecksumsOnInProgress(void);
-extern void SetDataChecksumsOn(void);
-extern void SetDataChecksumsOff(void);
+extern void SetDataChecksumsOn(bool fast);
+extern void SetDataChecksumsOff(bool fast);
extern const char *show_data_checksums(void);
extern const char *get_checksum_state_string(uint32 state);
extern void InitLocalDataChecksumState(void);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3cb84359adf..c7ef5a9c930 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12415,13 +12415,15 @@
# data checksum management functions
{ oid => '6507', descr => 'disable data checksums',
proname => 'pg_disable_data_checksums', provolatile => 'v',
- proparallel => 'r', prorettype => 'void', proargtypes => '',
- prosrc => 'disable_data_checksums', proacl => '{POSTGRES=X}' },
+ proparallel => 'r', prorettype => 'void', proargtypes => 'bool',
+ proallargtypes => '{bool}', proargmodes => '{i}', proargnames => '{fast}',
+ proargdefaults => '{true}', prosrc => 'disable_data_checksums',
+ proacl => '{POSTGRES=X}' },
{ oid => '6506', descr => 'enable data checksums',
proname => 'pg_enable_data_checksums', provolatile => 'v', proparallel => 'r',
- prorettype => 'void', proargtypes => 'int4 int4',
- proallargtypes => '{int4,int4}', proargmodes => '{i,i}',
- proargnames => '{cost_delay,cost_limit}', proargdefaults => '{0,100}',
+ prorettype => 'void', proargtypes => 'int4 int4 bool',
+ proallargtypes => '{int4,int4,bool}', proargmodes => '{i,i,i}',
+ proargnames => '{cost_delay,cost_limit,fast}', proargdefaults => '{0,100,true}',
prosrc => 'enable_data_checksums', proacl => '{POSTGRES=X}' },
# collation management functions
diff --git a/src/test/modules/test_checksums/t/DataChecksums/Utils.pm b/src/test/modules/test_checksums/t/DataChecksums/Utils.pm
index 3aa533d777f..77c208dd5fd 100644
--- a/src/test/modules/test_checksums/t/DataChecksums/Utils.pm
+++ b/src/test/modules/test_checksums/t/DataChecksums/Utils.pm
@@ -118,6 +118,11 @@ If defined, the function will wait for the state defined in this parameter,
waiting timing out, before returning. The function will wait for
$PostgreSQL::Test::Utils::timeout_default seconds before timing out.
+=item fast
+
+The B<fast> determines if checkpoints will be fast or spread, default is
+'true' (which means fast checkpoints).
+
=back
=cut
@@ -130,13 +135,14 @@ sub enable_data_checksums
# Set sane defaults for the parameters
$params{cost_delay} = 0 unless (defined($params{cost_delay}));
$params{cost_limit} = 100 unless (defined($params{cost_limit}));
+ $params{fast} = 'true' unless (defined($params{fast}));
my $query = <<'EOQ';
-SELECT pg_enable_data_checksums(%s, %s);
+SELECT pg_enable_data_checksums(%s, %s, %s);
EOQ
$postgresnode->safe_psql('postgres',
- sprintf($query, $params{cost_delay}, $params{cost_limit}));
+ sprintf($query, $params{cost_delay}, $params{cost_limit}, $params{fast}));
if (defined($params{wait}))
{
@@ -166,6 +172,11 @@ waiting timing out, before returning. The function will wait for
$PostgreSQL::Test::Utils::timeout_default seconds before timing out.
Unlike in C<enable_data_checksums> the value of the parameter is discarded.
+=item fast
+
+The B<fast> determines if checkpoints will be fast or spread, default is
+'true' (which means fast checkpoints).
+
=back
=cut
@@ -175,8 +186,15 @@ sub disable_data_checksums
my $postgresnode = shift;
my %params = @_;
+ # Set sane defaults for the parameters
+ $params{fast} = 'true' unless (defined($params{fast}));
+
+ my $query = <<'EOQ';
+SELECT pg_disable_data_checksums(%s);
+EOQ
+
$postgresnode->safe_psql('postgres',
- 'SELECT pg_disable_data_checksums();');
+ sprintf($query, $params{fast}));
if (defined($params{wait}))
{
--
2.54.0
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: allow spread checkpoints when changing checksums online
@ 2026-07-07 21:00 Daniel Gustafsson <[email protected]>
parent: Tomas Vondra <[email protected]>
0 siblings, 1 reply; 8+ messages in thread
From: Daniel Gustafsson @ 2026-07-07 21:00 UTC (permalink / raw)
To: Tomas Vondra <[email protected]>; +Cc: pgsql-hackers
> On 6 Jul 2026, at 13:43, Tomas Vondra <[email protected]> wrote:
> Here's a rebased patch, addressing the minor bitrot, and with some very
> minor adjustments.
Thanks for picking up this!
> 3) I've noticed the SGML docs don't have default values for the existing
> parameters (cost_delay, cost_limit), so I added those. Maybe backpatch?
+1, that sounds like a good idea.
> 4) I've added the new 'fast' parameter to the DataChecksums module, but
> mostly just for completeness. The TAP tests still use the default value,
> so that it doesn't take longer.
+ spread (throttled), which may increase the time needed to enable checksums,
I think we should stick to the "data checksums" terminology for consistency.
@@ -1676,6 +1686,7 @@ DataChecksumsWorkerMain(Datum arg)
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
}
else
costs_updated = false;
This update will only change the fast parameter if cost_limit or cost_delay
were changed, shouldn't the fast parameter also be checked for runtime update?
> I've spent some time thinking about the default value. For a while I
> thought maybe it should default to 'false' (in which case we use spread
> checkpoints, which is the less disruptive option).
>
> But that's actually futile, because the cost_delay still defaults to 0,
> which means the "data page rewrite" phase won't be paced. It seems
> surprising the first phase would not be throttled by default, while the
> checkpoints are ...
>
> So I ended up setting the 'fast=true' default.
I think fast=true is the right default.
> This is not a very complicated patch, and it's been part of the old
> patch series for quite a while. So unless there's some objections I'll
> get this committed in a couple days.
+1
--
Daniel Gustafsson
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: allow spread checkpoints when changing checksums online
@ 2026-07-07 22:36 Tomas Vondra <[email protected]>
parent: Daniel Gustafsson <[email protected]>
0 siblings, 2 replies; 8+ messages in thread
From: Tomas Vondra @ 2026-07-07 22:36 UTC (permalink / raw)
To: Daniel Gustafsson <[email protected]>; +Cc: pgsql-hackers
On 7/7/26 23:00, Daniel Gustafsson wrote:
>> On 6 Jul 2026, at 13:43, Tomas Vondra <[email protected]> wrote:
>
>> Here's a rebased patch, addressing the minor bitrot, and with some very
>> minor adjustments.
>
> Thanks for picking up this!
>
>> 3) I've noticed the SGML docs don't have default values for the existing
>> parameters (cost_delay, cost_limit), so I added those. Maybe backpatch?
>
> +1, that sounds like a good idea.
>
>> 4) I've added the new 'fast' parameter to the DataChecksums module, but
>> mostly just for completeness. The TAP tests still use the default value,
>> so that it doesn't take longer.
>
> + spread (throttled), which may increase the time needed to enable checksums,
>
> I think we should stick to the "data checksums" terminology for consistency.
>
> @@ -1676,6 +1686,7 @@ DataChecksumsWorkerMain(Datum arg)
>
> DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
> DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
> + DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
> }
> else
> costs_updated = false;
>
> This update will only change the fast parameter if cost_limit or cost_delay
> were changed, shouldn't the fast parameter also be checked for runtime update?
>
Ah, good catch. I missed that. The attached v3 fixes this.
>> I've spent some time thinking about the default value. For a while I
>> thought maybe it should default to 'false' (in which case we use spread
>> checkpoints, which is the less disruptive option).
>>
>> But that's actually futile, because the cost_delay still defaults to 0,
>> which means the "data page rewrite" phase won't be paced. It seems
>> surprising the first phase would not be throttled by default, while the
>> checkpoints are ...
>>
>> So I ended up setting the 'fast=true' default.
>
> I think fast=true is the right default.
>
Ack
>> This is not a very complicated patch, and it's been part of the old
>> patch series for quite a while. So unless there's some objections I'll
>> get this committed in a couple days.
>
> +1
Thanks!
--
Tomas Vondra
Attachments:
[text/x-patch] v3-0001-Allow-using-spread-checkpoints-when-enabling-disa.patch (16.4K, ../../[email protected]/2-v3-0001-Allow-using-spread-checkpoints-when-enabling-disa.patch)
download | inline diff:
From b632d2b4e1c2904ab26cf1fdfc874e71f59d2a5a Mon Sep 17 00:00:00 2001
From: Tomas Vondra <[email protected]>
Date: Mon, 6 Jul 2026 11:31:19 +0200
Subject: [PATCH v3] Allow using spread checkpoints when enabling/disabling
checksums
This commit allows using spread (throttled) checkpoints while enabling
or disabling data checksums in a running cluster, to limit the impact on
the rest of the system.
While enabling checksums, the process has to rewrite all data pages, and
then perform perform checkpoints at certain points. It was possible to
throttle the rewriting of data pages, to limit the impact on the rest of
the cluster, the ckeckpoints were always issued as CHECKPOINT_FAST. This
can be very disruptive.
When disabling checksums, it's not necessary to rewrite any data pages,
but the checkpoint may still trigger a lot of I/O. So a seemingly cheap
operation (disabling checksums) may get rather disruptive.
This commit introduces a new "fast" parameter for functions initiating
the checksum state change. The default "fast=true" means the requested
checkpoints are fast.
---
doc/src/sgml/func/func-admin.sgml | 22 ++++++++++++--
src/backend/access/transam/xlog.c | 24 +++++++++++----
src/backend/postmaster/datachecksum_state.c | 30 +++++++++++++------
src/include/access/xlog.h | 4 +--
src/include/catalog/pg_proc.dat | 12 ++++----
.../test_checksums/t/DataChecksums/Utils.pm | 24 +++++++++++++--
6 files changed, 89 insertions(+), 27 deletions(-)
diff --git a/doc/src/sgml/func/func-admin.sgml b/doc/src/sgml/func/func-admin.sgml
index 0eae1c1f616..97b768638c5 100644
--- a/doc/src/sgml/func/func-admin.sgml
+++ b/doc/src/sgml/func/func-admin.sgml
@@ -3158,7 +3158,7 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
<indexterm>
<primary>pg_enable_data_checksums</primary>
</indexterm>
- <function>pg_enable_data_checksums</function> ( <optional><parameter>cost_delay</parameter> <type>int</type>, <parameter>cost_limit</parameter> <type>int</type></optional> )
+ <function>pg_enable_data_checksums</function> ( <optional><parameter>cost_delay</parameter> <type>int</type> <literal>DEFAULT</literal> <literal>0</literal>, <parameter>cost_limit</parameter> <type>int</type> <literal>DEFAULT</literal> <literal>100</literal>, <parameter>fast</parameter> <type>bool</type> <literal>DEFAULT</literal> <literal>true</literal></optional> )
<returnvalue>void</returnvalue>
</para>
<para>
@@ -3175,6 +3175,15 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
specified, the process is throttled using the same principles as
<link linkend="runtime-config-resource-vacuum-cost">Cost-based Vacuum Delay</link>.
</para>
+ <para>
+ The <parameter>fast</parameter> specifies whether the checkpoints performed
+ are fast or spread.
+ When set to <literal>true</literal> the checkpoints are fast, which may cause
+ a spike in I/O. When set to <literal>false</literal>, the checkpoints are
+ spread (throttled), which may increase the time needed to enable checksums,
+ but it limits the impact on the system.
+ The default value is <literal>true</literal>.
+ </para>
</entry>
</row>
@@ -3183,7 +3192,7 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
<indexterm>
<primary>pg_disable_data_checksums</primary>
</indexterm>
- <function>pg_disable_data_checksums</function> ()
+ <function>pg_disable_data_checksums</function> ( <optional><parameter>fast</parameter> <type>bool</type> <literal>DEFAULT</literal> <literal>false</literal></optional> )
<returnvalue>void</returnvalue>
</para>
<para>
@@ -3193,6 +3202,15 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
stopped validating data checksums, the data checksum state will be
set to <literal>off</literal>.
</para>
+ <para>
+ The <parameter>fast</parameter> specifies whether the checkpoints performed
+ are fast or spread.
+ When set to <literal>true</literal> the checkpoints are fast, which may cause
+ a spike in I/O. When set to <literal>false</literal>, the checkpoints are
+ spread (throttled), which may increase the time needed to disable checksums,
+ but it limits the impact on the system.
+ The default value is <literal>true</literal>.
+ </para>
</entry>
</row>
</tbody>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index a81912b7441..aaca0437a5f 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4799,9 +4799,10 @@ SetDataChecksumsOnInProgress(void)
* state transition.
*/
void
-SetDataChecksumsOn(void)
+SetDataChecksumsOn(bool fast)
{
uint64 barrier;
+ int flags;
SpinLockAcquire(&XLogCtl->info_lck);
@@ -4815,7 +4816,7 @@ SetDataChecksumsOn(void)
SpinLockRelease(&XLogCtl->info_lck);
elog(WARNING,
"cannot set data checksums to \"on\", current state is not \"inprogress-on\", disabling");
- SetDataChecksumsOff();
+ SetDataChecksumsOff(fast);
return;
}
@@ -4845,7 +4846,12 @@ SetDataChecksumsOn(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ /* determine flags for the checkpoint */
+ flags = CHECKPOINT_FORCE | CHECKPOINT_WAIT;
+ if (fast)
+ flags |= CHECKPOINT_FAST;
+
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
}
@@ -4863,9 +4869,15 @@ SetDataChecksumsOn(void)
* state transition.
*/
void
-SetDataChecksumsOff(void)
+SetDataChecksumsOff(bool fast)
{
uint64 barrier;
+ int flags;
+
+ /* determine flags for the checkpoint(s) */
+ flags = CHECKPOINT_FORCE | CHECKPOINT_WAIT;
+ if (fast)
+ flags |= CHECKPOINT_FAST;
SpinLockAcquire(&XLogCtl->info_lck);
@@ -4907,7 +4919,7 @@ SetDataChecksumsOff(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
/*
@@ -4945,7 +4957,7 @@ SetDataChecksumsOff(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
}
diff --git a/src/backend/postmaster/datachecksum_state.c b/src/backend/postmaster/datachecksum_state.c
index 68557c16cb9..bff73535e8e 100644
--- a/src/backend/postmaster/datachecksum_state.c
+++ b/src/backend/postmaster/datachecksum_state.c
@@ -307,6 +307,7 @@ typedef struct DataChecksumsStateStruct
DataChecksumsWorkerOperation launch_operation;
int launch_cost_delay;
int launch_cost_limit;
+ bool launch_fast_checkpoint;
/*
* Is a launcher process currently running? This is set by the main
@@ -340,6 +341,7 @@ typedef struct DataChecksumsStateStruct
DataChecksumsWorkerOperation operation;
int cost_delay;
int cost_limit;
+ bool fast_checkpoint;
/*
* Signaling between the launcher and the worker process. Protected by
@@ -382,7 +384,8 @@ static DataChecksumsWorkerOperation operation;
/* Prototypes */
static void StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
int cost_delay,
- int cost_limit);
+ int cost_limit,
+ bool fast);
static void DataChecksumsShmemRequest(void *arg);
static bool DatabaseExists(Oid dboid);
static List *BuildDatabaseList(void);
@@ -543,6 +546,8 @@ AbsorbDataChecksumsBarrier(ProcSignalBarrierType barrier)
Datum
disable_data_checksums(PG_FUNCTION_ARGS)
{
+ bool fast = PG_GETARG_BOOL(0);
+
PreventCommandDuringRecovery("pg_disable_data_checksums()");
if (!superuser())
@@ -550,7 +555,7 @@ disable_data_checksums(PG_FUNCTION_ARGS)
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to change data checksum state"));
- StartDataChecksumsWorkerLauncher(DISABLE_DATACHECKSUMS, 0, 0);
+ StartDataChecksumsWorkerLauncher(DISABLE_DATACHECKSUMS, 0, 0, fast);
PG_RETURN_VOID();
}
@@ -564,6 +569,7 @@ enable_data_checksums(PG_FUNCTION_ARGS)
{
int cost_delay = PG_GETARG_INT32(0);
int cost_limit = PG_GETARG_INT32(1);
+ bool fast = PG_GETARG_BOOL(2);
PreventCommandDuringRecovery("pg_enable_data_checksums()");
@@ -582,7 +588,7 @@ enable_data_checksums(PG_FUNCTION_ARGS)
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cost limit must be greater than zero"));
- StartDataChecksumsWorkerLauncher(ENABLE_DATACHECKSUMS, cost_delay, cost_limit);
+ StartDataChecksumsWorkerLauncher(ENABLE_DATACHECKSUMS, cost_delay, cost_limit, fast);
PG_RETURN_VOID();
}
@@ -602,7 +608,8 @@ enable_data_checksums(PG_FUNCTION_ARGS)
static void
StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
int cost_delay,
- int cost_limit)
+ int cost_limit,
+ bool fast)
{
BackgroundWorker bgw;
BackgroundWorkerHandle *bgw_handle;
@@ -622,6 +629,7 @@ StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
DataChecksumState->launch_operation = op;
DataChecksumState->launch_cost_delay = cost_delay;
DataChecksumState->launch_cost_limit = cost_limit;
+ DataChecksumState->launch_fast_checkpoint = fast;
/* Is the launcher already running? If so, what is it doing? */
running = DataChecksumState->launcher_running;
@@ -989,7 +997,7 @@ launcher_exit(int code, Datum arg)
* the state to off since processing cannot be resumed.
*/
if (DataChecksumsInProgressOn())
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
launcher_running = false;
@@ -1130,6 +1138,7 @@ DataChecksumsWorkerLauncherMain(Datum arg)
DataChecksumState->operation = operation;
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
LWLockRelease(DataChecksumsWorkerLock);
/*
@@ -1184,7 +1193,7 @@ again:
* Data checksums have been set on all pages, set the state to on in
* order to instruct backends to validate checksums on reading.
*/
- SetDataChecksumsOn();
+ SetDataChecksumsOn(DataChecksumState->fast_checkpoint);
ereport(LOG,
errmsg("data checksums are now enabled"));
@@ -1196,7 +1205,7 @@ again:
pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_PHASE,
PROGRESS_DATACHECKSUMS_PHASE_DISABLING);
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
ereport(LOG,
errmsg("data checksums are now disabled"));
}
@@ -1224,6 +1233,7 @@ done:
operation = DataChecksumState->launch_operation;
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
LWLockRelease(DataChecksumsWorkerLock);
goto again;
}
@@ -1313,7 +1323,7 @@ ProcessAllDatabases(void)
* Disable checksums on cluster, because we failed one of the
* databases and this is an all or nothing process.
*/
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
ereport(ERROR,
errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("data checksums failed to get enabled in all databases, aborting"),
@@ -1667,7 +1677,8 @@ DataChecksumsWorkerMain(Datum arg)
break;
}
if ((DataChecksumState->launch_cost_delay != DataChecksumState->cost_delay)
- || (DataChecksumState->launch_cost_limit != DataChecksumState->cost_limit))
+ || (DataChecksumState->launch_cost_limit != DataChecksumState->cost_limit)
+ || (DataChecksumState->launch_fast_checkpoint != DataChecksumState->fast_checkpoint))
{
costs_updated = true;
VacuumCostDelay = DataChecksumState->launch_cost_delay;
@@ -1676,6 +1687,7 @@ DataChecksumsWorkerMain(Datum arg)
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
}
else
costs_updated = false;
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 4dd98624204..8a9e8961a6a 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -253,8 +253,8 @@ extern bool DataChecksumsOn(void);
extern bool DataChecksumsOff(void);
extern bool DataChecksumsInProgressOn(void);
extern void SetDataChecksumsOnInProgress(void);
-extern void SetDataChecksumsOn(void);
-extern void SetDataChecksumsOff(void);
+extern void SetDataChecksumsOn(bool fast);
+extern void SetDataChecksumsOff(bool fast);
extern const char *show_data_checksums(void);
extern const char *get_checksum_state_string(uint32 state);
extern void InitLocalDataChecksumState(void);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3cb84359adf..c7ef5a9c930 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12415,13 +12415,15 @@
# data checksum management functions
{ oid => '6507', descr => 'disable data checksums',
proname => 'pg_disable_data_checksums', provolatile => 'v',
- proparallel => 'r', prorettype => 'void', proargtypes => '',
- prosrc => 'disable_data_checksums', proacl => '{POSTGRES=X}' },
+ proparallel => 'r', prorettype => 'void', proargtypes => 'bool',
+ proallargtypes => '{bool}', proargmodes => '{i}', proargnames => '{fast}',
+ proargdefaults => '{true}', prosrc => 'disable_data_checksums',
+ proacl => '{POSTGRES=X}' },
{ oid => '6506', descr => 'enable data checksums',
proname => 'pg_enable_data_checksums', provolatile => 'v', proparallel => 'r',
- prorettype => 'void', proargtypes => 'int4 int4',
- proallargtypes => '{int4,int4}', proargmodes => '{i,i}',
- proargnames => '{cost_delay,cost_limit}', proargdefaults => '{0,100}',
+ prorettype => 'void', proargtypes => 'int4 int4 bool',
+ proallargtypes => '{int4,int4,bool}', proargmodes => '{i,i,i}',
+ proargnames => '{cost_delay,cost_limit,fast}', proargdefaults => '{0,100,true}',
prosrc => 'enable_data_checksums', proacl => '{POSTGRES=X}' },
# collation management functions
diff --git a/src/test/modules/test_checksums/t/DataChecksums/Utils.pm b/src/test/modules/test_checksums/t/DataChecksums/Utils.pm
index 3aa533d777f..77c208dd5fd 100644
--- a/src/test/modules/test_checksums/t/DataChecksums/Utils.pm
+++ b/src/test/modules/test_checksums/t/DataChecksums/Utils.pm
@@ -118,6 +118,11 @@ If defined, the function will wait for the state defined in this parameter,
waiting timing out, before returning. The function will wait for
$PostgreSQL::Test::Utils::timeout_default seconds before timing out.
+=item fast
+
+The B<fast> determines if checkpoints will be fast or spread, default is
+'true' (which means fast checkpoints).
+
=back
=cut
@@ -130,13 +135,14 @@ sub enable_data_checksums
# Set sane defaults for the parameters
$params{cost_delay} = 0 unless (defined($params{cost_delay}));
$params{cost_limit} = 100 unless (defined($params{cost_limit}));
+ $params{fast} = 'true' unless (defined($params{fast}));
my $query = <<'EOQ';
-SELECT pg_enable_data_checksums(%s, %s);
+SELECT pg_enable_data_checksums(%s, %s, %s);
EOQ
$postgresnode->safe_psql('postgres',
- sprintf($query, $params{cost_delay}, $params{cost_limit}));
+ sprintf($query, $params{cost_delay}, $params{cost_limit}, $params{fast}));
if (defined($params{wait}))
{
@@ -166,6 +172,11 @@ waiting timing out, before returning. The function will wait for
$PostgreSQL::Test::Utils::timeout_default seconds before timing out.
Unlike in C<enable_data_checksums> the value of the parameter is discarded.
+=item fast
+
+The B<fast> determines if checkpoints will be fast or spread, default is
+'true' (which means fast checkpoints).
+
=back
=cut
@@ -175,8 +186,15 @@ sub disable_data_checksums
my $postgresnode = shift;
my %params = @_;
+ # Set sane defaults for the parameters
+ $params{fast} = 'true' unless (defined($params{fast}));
+
+ my $query = <<'EOQ';
+SELECT pg_disable_data_checksums(%s);
+EOQ
+
$postgresnode->safe_psql('postgres',
- 'SELECT pg_disable_data_checksums();');
+ sprintf($query, $params{fast}));
if (defined($params{wait}))
{
--
2.54.0
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: allow spread checkpoints when changing checksums online
@ 2026-07-08 08:11 Daniel Gustafsson <[email protected]>
parent: Tomas Vondra <[email protected]>
1 sibling, 0 replies; 8+ messages in thread
From: Daniel Gustafsson @ 2026-07-08 08:11 UTC (permalink / raw)
To: Tomas Vondra <[email protected]>; +Cc: pgsql-hackers
> On 8 Jul 2026, at 00:36, Tomas Vondra <[email protected]> wrote:
> On 7/7/26 23:00, Daniel Gustafsson wrote:
>> This update will only change the fast parameter if cost_limit or cost_delay
>> were changed, shouldn't the fast parameter also be checked for runtime update?
>
> Ah, good catch. I missed that. The attached v3 fixes this.
LGTM
--
Daniel Gustafsson
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: allow spread checkpoints when changing checksums online
@ 2026-07-08 11:53 Ewan Young <[email protected]>
parent: Tomas Vondra <[email protected]>
1 sibling, 1 reply; 8+ messages in thread
From: Ewan Young @ 2026-07-08 11:53 UTC (permalink / raw)
To: Tomas Vondra <[email protected]>; +Cc: Daniel Gustafsson <[email protected]>; pgsql-hackers
Hi Tomas,
Thanks for v3. One small documentation inconsistency in the disable
function before this goes in.
In func-admin.sgml the signature of pg_disable_data_checksums documents
the default as false:
pg_disable_data_checksums ( fast bool DEFAULT false )
but the actual default is true. pg_proc.dat sets
proargdefaults => '{true}'
and the prose you added right below the signature also says:
The default value is true.
On Wed, Jul 8, 2026 at 6:36 AM Tomas Vondra <[email protected]> wrote:
>
> On 7/7/26 23:00, Daniel Gustafsson wrote:
> >> On 6 Jul 2026, at 13:43, Tomas Vondra <[email protected]> wrote:
> >
> >> Here's a rebased patch, addressing the minor bitrot, and with some very
> >> minor adjustments.
> >
> > Thanks for picking up this!
> >
> >> 3) I've noticed the SGML docs don't have default values for the existing
> >> parameters (cost_delay, cost_limit), so I added those. Maybe backpatch?
> >
> > +1, that sounds like a good idea.
> >
> >> 4) I've added the new 'fast' parameter to the DataChecksums module, but
> >> mostly just for completeness. The TAP tests still use the default value,
> >> so that it doesn't take longer.
> >
> > + spread (throttled), which may increase the time needed to enable checksums,
> >
> > I think we should stick to the "data checksums" terminology for consistency.
> >
> > @@ -1676,6 +1686,7 @@ DataChecksumsWorkerMain(Datum arg)
> >
> > DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
> > DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
> > + DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
> > }
> > else
> > costs_updated = false;
> >
> > This update will only change the fast parameter if cost_limit or cost_delay
> > were changed, shouldn't the fast parameter also be checked for runtime update?
> >
>
> Ah, good catch. I missed that. The attached v3 fixes this.
>
> >> I've spent some time thinking about the default value. For a while I
> >> thought maybe it should default to 'false' (in which case we use spread
> >> checkpoints, which is the less disruptive option).
> >>
> >> But that's actually futile, because the cost_delay still defaults to 0,
> >> which means the "data page rewrite" phase won't be paced. It seems
> >> surprising the first phase would not be throttled by default, while the
> >> checkpoints are ...
> >>
> >> So I ended up setting the 'fast=true' default.
> >
> > I think fast=true is the right default.
> >
>
> Ack
>
> >> This is not a very complicated patch, and it's been part of the old
> >> patch series for quite a while. So unless there's some objections I'll
> >> get this committed in a couple days.
> >
> > +1
>
> Thanks!
>
> --
> Tomas Vondra
--
Regards,
Ewan Young
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: allow spread checkpoints when changing checksums online
@ 2026-07-08 13:30 Daniel Gustafsson <[email protected]>
parent: Ewan Young <[email protected]>
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Gustafsson @ 2026-07-08 13:30 UTC (permalink / raw)
To: Ewan Young <[email protected]>; +Cc: Tomas Vondra <[email protected]>; pgsql-hackers
> On 8 Jul 2026, at 13:53, Ewan Young <[email protected]> wrote:
> In func-admin.sgml the signature of pg_disable_data_checksums documents
> the default as false:
>
> pg_disable_data_checksums ( fast bool DEFAULT false )
> but the actual default is true. pg_proc.dat sets
Nice catch and +1, I missed that one.
--
Daniel Gustafsson
^ permalink raw reply [nested|flat] 8+ messages in thread
end of thread, other threads:[~2026-07-08 13:30 UTC | newest]
Thread overview: 8+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-04-30 05:06 [PATCH 1/2] Move tablespace cleanup out of pg_regress. Kyotaro Horiguchi <[email protected]>
2026-05-04 13:42 allow spread checkpoints when changing checksums online Tomas Vondra <[email protected]>
2026-07-06 11:43 ` Re: allow spread checkpoints when changing checksums online Tomas Vondra <[email protected]>
2026-07-07 21:00 ` Re: allow spread checkpoints when changing checksums online Daniel Gustafsson <[email protected]>
2026-07-07 22:36 ` Re: allow spread checkpoints when changing checksums online Tomas Vondra <[email protected]>
2026-07-08 08:11 ` Re: allow spread checkpoints when changing checksums online Daniel Gustafsson <[email protected]>
2026-07-08 11:53 ` Re: allow spread checkpoints when changing checksums online Ewan Young <[email protected]>
2026-07-08 13:30 ` Re: allow spread checkpoints when changing checksums online Daniel Gustafsson <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox