On Wed, 23 Jul 2025 at 09:24, Fujii Masao <masao.fu...@gmail.com> wrote: > On Mon, Jul 21, 2025 at 2:38 PM Japin Li <japi...@hotmail.com> wrote: >> >> >> Hi, hackers, >> >> I was recently reviewing the KeepFileRestoredFromArchive() function and came >> across a section that raised a question for me: >> >> /* >> * Create .done file forcibly to prevent the restored segment from being >> * archived again later. >> */ >> if (XLogArchiveMode != ARCHIVE_MODE_ALWAYS) >> XLogArchiveForceDone(xlogfname); >> else >> XLogArchiveNotify(xlogfname); >> >> My understanding is that the WAL segment in this context has just been >> restored from the archive. >> >> However, for archive_mode=always, the code calls >> XLogArchiveNotify(xlogfname), >> which, if I understand correctly, signals the archiver to re-archive this >> already-archived WAL segment. >> >> Is there a specific scenario or benefit I'm overlooking? > > One possible scenario is when the archive directory used by restore_command > is different from the one used by archive_command. For example, the primary > and standby servers might each have their own separate archive directories, > with archive_command configured to archive WAL files to their > respective directories. > Meanwhile, the standby’s restore_command might be set up to fetch WAL files > from the primary’s archive directory. This kind of setup can be used > when there’s > no shared archive directory between the primary and standby. In such cases, > even WAL files restored on the standby might need to be archived again. >
Thanks for your explanation. Yes, I've encountered this exact scenario: when promoting a standby and then re-joining the old primary, they maintain separate WAL archive directories. I've attached a script to reproduce this. I've observed that WalReceiverMain() archives WALs upon receipt, and StartupXLOG() subsequently restores them from the archive directory, and then re-archives them via KeepFileRestoredFromArchive(). -- Regards, Japin Li
#!/bin/bash # Cleanup the data. rm -rf /tmp/{pgdata,arch,log}{1,2} # Create the archive directories. mkdir -p /tmp/arch{1,2} # Initialize the primary node. initdb -k -D /tmp/pgdata1 -U jerry cat <<EOF >>/tmp/pgdata1/postgresql.auto.conf port = '9967' archive_mode = 'always' archive_command = 'test ! -f /tmp/arch1/%f && cp %p /tmp/arch1/%f' restore_command = 'cp /tmp/arch1/%f %p' logging_collector = 'on' log_destination = 'csvlog' log_filename = 'postgresql-%d.log' log_directory = '/tmp/log1' EOF # Startup the primary node. pg_ctl -l 1.log -D /tmp/pgdata1 start # Create the standby node. pg_basebackup -U jerry -h localhost -p 9967 -R -Fp -Xs -P -D /tmp/pgdata2 cat <<EOF >>/tmp/pgdata2/postgresql.auto.conf port = '9968' archive_mode = 'always' archive_command = 'test ! -f /tmp/arch2/%f && cp %p /tmp/arch2/%f' restore_command = 'cp /tmp/arch2/%f %p' logging_collector = 'on' log_destination = 'csvlog' log_filename = 'postgresql-%d.log' log_directory = '/tmp/log2' EOF # Startup the standby node. pg_ctl -l 2.log -D /tmp/pgdata2 start # Check the replication. psql -U jerry -p 9967 postgres -xc 'select * from pg_stat_replication' # Stop the primary and then promote the standby to new primary. pg_ctl -l 1.log -D /tmp/pgdata1 stop pg_ctl -l 2.log -D /tmp/pgdata2 promote # Re-join the old primary as new standby. cat <<EOF >>/tmp/pgdata1/postgresql.auto.conf primary_conninfo = 'user=jerry host=localhost port=9968' EOF touch /tmp/pgdata1/standby.signal pg_ctl -l 1.log -D /tmp/pgdata1 start # Check the replication psql -U jerry -p 9968 postgres -xc 'select * from pg_stat_replication' # Check the archiver process status. ps -ef | grep archiver pg_ctl -l 2.log -D /tmp/pgdata2 stop pg_ctl -l 1.log -D /tmp/pgdata1 stop