Add -k/--link option to pg_combinebackup

From: Israel Barth Rubio <barthisrael(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Add -k/--link option to pg_combinebackup
Date: 2025-01-15 17:42:23
Message-ID: CAO_rXXBS0NictfmXodASjxqKgFDtUj_J1xUL100oeGJ3Mt+K8w@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hello all,

With the current implementation of pg_combinebackup, we have a few
copy methods: --clone, --copy and --copy-file-range. By using either of
them, it implicates an actual file copy in the file system, i.e. among
other things, disk usage.

While discussing with some people, e.g. Robert Haas and Martín Marqués,
about possible ways to improve pg_combinebackup performance and/or
reduce disk usage taken by the synthetic backup, there was a thought
of using hard links.

I'm submitting a patch in this thread which introduces the -k/--link
option to pg_combinebackup, making it similar to the options exposed
by pg_upgrade. The patch reuses the same code flow that already exists
in pg_combinebackup, and whenever the tool judges a file should be
copied from either of the input backups to the synthetic backup, if the
link mode was chosen, a hard link is created instead of performing a
copy.

Depending on the pattern of modification of PGDATA files between
backups (based on the workload), the user might face improved
performance of pg_combinebackup as well as lower disk usage by the
synthetic backup.

That enhancement comes at a cost: the input backups may be invalidated
if the user modified the shared files from the synthetic backup, or if
the user starts the cluster from the synthetic backup. With that in
mind, a warning has been added to pg_combinebackup, as well as to the
docs, recommending that the user moves the synthetic backup to another
file system or machine before making use of it.

I've run the existing test suite with --link option and it worked fine,
except for an issue when running pg_verifybackup in t/003_timeline.pl.
The issue was expected given the description shared above. I modified
the tests to behave slightly differently depending on the copy method
selected by the runner.

Besides that, you can find below the outcomes of manual testing:

* Create some tables:

postgres=# CREATE TABLE test_1 AS SELECT generate_series(1, 1000000);
SELECT 1000000
postgres=# CREATE TABLE test_2 AS SELECT generate_series(1, 1000000);
SELECT 1000000
postgres=# CREATE TABLE test_3 AS SELECT generate_series(1, 1000000);
SELECT 1000000

* Check their OID:

postgres=# SELECT oid, relname FROM pg_class WHERE relname LIKE 'test_%';
oid | relname
-------+---------
16388 | test_1
16391 | test_2
16394 | test_3
(3 rows)

* Enable the WAL summarizer:

postgres=# ALTER SYSTEM SET summarize_wal TO on;
ALTER SYSTEM
postgres=# SELECT pg_reload_conf();
pg_reload_conf
----------------
t
(1 row)

* Take a full backup:

$ pg_basebackup -d 'dbname=postgres' -D ~/monday -c fast -Xn
NOTICE: WAL archiving is not enabled; you must ensure that all required
WAL segments are copied through other means to complete the backup

* Perform an update that will touch the whole file:

postgres=# UPDATE test_2 SET generate_series = generate_series + 1;
UPDATE 1000000

* Perform an update that will touch a single page:

postgres=# UPDATE test_3 SET generate_series = generate_series + 1 WHERE
generate_series = 1;
UPDATE 1

* Take an incremental backup:

$ pg_basebackup -d 'dbname=postgres' -D ~/tuesday -c fast -Xn --incremental
~/monday/backup_manifest
NOTICE: WAL archiving is not enabled; you must ensure that all required
WAL segments are copied through other means to complete the backup

* Check a dry run of pg_combinebackup, focusing on the OIDs of the
tables:

$ pg_combinebackup -d -n --link -o ~/tuesday_full ~/monday ~/tuesday/ 2>&1
| grep -P '16388|16391|16394'
pg_combinebackup: would copy "/home/vagrant/monday/base/5/16388" to
"/home/vagrant/tuesday_full/base/5/16388" using strategy link
pg_combinebackup: would copy "/home/vagrant/tuesday//base/5/16391" to
"/home/vagrant/tuesday_full/base/5/16391" using strategy link
pg_combinebackup: would reconstruct
"/home/vagrant/tuesday_full/base/5/16394" (4480 blocks, checksum CRC32C)
pg_combinebackup: reconstruction plan:
0:/home/vagrant/tuesday//base/5/INCREMENTAL(dot)16394(at)8192
1-4423:/home/vagrant/monday/base/5/16394(at)36233216
4424:/home/vagrant/tuesday//base/5/INCREMENTAL(dot)16394(at)16384
4425-4479:/home/vagrant/monday/base/5/16394(at)36691968
pg_combinebackup: would have read 4478 blocks from
"/home/vagrant/monday/base/5/16394"
pg_combinebackup: would have read 2 blocks from
"/home/vagrant/tuesday//base/5/INCREMENTAL.16394"
pg_combinebackup: would copy "/home/vagrant/monday/base/5/16388_vm" to
"/home/vagrant/tuesday_full/base/5/16388_vm" using strategy link
pg_combinebackup: would copy "/home/vagrant/tuesday//base/5/16388_fsm" to
"/home/vagrant/tuesday_full/base/5/16388_fsm" using strategy link
pg_combinebackup: would copy "/home/vagrant/tuesday//base/5/16391_vm" to
"/home/vagrant/tuesday_full/base/5/16391_vm" using strategy link
pg_combinebackup: would copy "/home/vagrant/tuesday//base/5/16391_fsm" to
"/home/vagrant/tuesday_full/base/5/16391_fsm" using strategy link
pg_combinebackup: would copy "/home/vagrant/monday/base/5/16394_vm" to
"/home/vagrant/tuesday_full/base/5/16394_vm" using strategy link
pg_combinebackup: would copy "/home/vagrant/tuesday//base/5/16394_fsm" to
"/home/vagrant/tuesday_full/base/5/16394_fsm" using strategy link

* Create a synthetic backup:
$ pg_combinebackup --link -o ~/tuesday_full ~/monday ~/tuesday
pg_combinebackup: warning: Modifying files or starting the cluster from the
synthetic backup might invalidate one or more of the input backups
pg_combinebackup: hint: It is recommended to move the synthetic backup to
another file system or machine before performing changes and/or starting
the cluster

* Check files with link counter set to 1:

$ find ~/tuesday_full -type f -links 1
/home/vagrant/tuesday_full/backup_label
/home/vagrant/tuesday_full/base/5/1259
/home/vagrant/tuesday_full/base/5/2619
/home/vagrant/tuesday_full/base/5/16394
/home/vagrant/tuesday_full/backup_manifest

* Check files with link counter set to 2, focusing on the OIDs of the
tables:

$ find ~/tuesday_full -type f -links 2 | grep -P '16388|16391|16394'
/home/vagrant/tuesday_full/base/5/16388
/home/vagrant/tuesday_full/base/5/16391
/home/vagrant/tuesday_full/base/5/16388_vm
/home/vagrant/tuesday_full/base/5/16388_fsm
/home/vagrant/tuesday_full/base/5/16391_vm
/home/vagrant/tuesday_full/base/5/16391_fsm
/home/vagrant/tuesday_full/base/5/16394_vm
/home/vagrant/tuesday_full/base/5/16394_fsm

(There are many other linked files).

Attachment Content-Type Size
v1-0001-pg_combinebackup-add-support-for-hard-links.patch application/octet-stream 10.7 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Masahiko Sawada 2025-01-15 17:55:51 Re: POC: enable logical decoding when wal_level = 'replica' without a server restart
Previous Message Masahiko Sawada 2025-01-15 17:27:54 Re: POC: enable logical decoding when wal_level = 'replica' without a server restart