follow: release the source snapshot connection after the catalog read - #53
Open
teknogeek0 wants to merge 1 commit into
Open
follow: release the source snapshot connection after the catalog read#53teknogeek0 wants to merge 1 commit into
teknogeek0 wants to merge 1 commit into
Conversation
`pgcopydb follow` (standalone, e.g. `follow --resume`) opened a source connection to hold a snapshot for the initial catalog read, then never closed it — it stayed idle in transaction on the source for the entire follow run (which can be days). On a --resume run the catalog read is a cache hit, so the connection is opened and never even used, yet still held. The follow phase streams from the replication slot, and the database setup and sequence-reset steps each open their own connection (via copydb_copy_snapshot), so nothing needs this connection after the catalog read. Close it right after, mirroring clone --follow, which already closes its snapshot once the base copy is done. Gate the close on the live connection rather than sourceSnapshot.state: when the catalog read runs, copydb_fetch_schema_and_prepare_specs commits and finishes this connection itself but leaves state as SET, so state is unreliable. A non-NULL connection means the fetch left it open and it is ours to close; a NULL connection means it was already torn down. It holds no snapshot in the --resume case (backend_xmin is NULL), so this is a connection-hygiene fix, not a vacuum-horizon fix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Standalone
pgcopydb follow(notablyfollow --resume) opens a source connection to hold a snapshot for the one-time initial catalog read, and then never closes it. It sits idle in transaction on the source for the entire follow run — which for an online migration can be days.On a
--resumerun it's worse: the catalog read is a cache hit (the source catalog was already fetched into the local SQLite state in a prior run), socopydb_fetch_schema_and_prepare_specsreturns early via "Re-using catalog caches" and this connection is opened and never even used, yet still held open for the whole run.It holds no snapshot in that case (
backend_xminis NULL), so this is a connection-hygiene issue, not a vacuum-horizon one — but a long-lived idle-in-transaction connection is exactly the kind of thing that alarms source DBAs and would become a real problem if that transaction ever acquired a snapshot.Fix
Close the source snapshot connection in
cli_followright after the catalog read. The follow phase streams from the replication slot, and the database setup and sequence-reset steps each open their own connection (viacopydb_copy_snapshot, which copies the snapshot metadata into a fresh connection), so nothing uses this connection again. This mirrorsclone --follow, which already closes its snapshot once the base copy is done (cli_clone_follow.cclone_and_follow).The close is gated on the live connection (
sourceSnapshot.pgsql.connection != NULL), notsourceSnapshot.state: when the catalog read actually runs,copydb_fetch_schema_and_prepare_specscommits and finishes this connection itself but leavesstateasSET, sostateis unreliable here. A non-NULL connection means the fetch left it open (cache-hit / not-consistent cases) and it's ours to close; a NULL connection means it was already torn down. (An earlier version gated onstateand hitBUG: pgsql_commit() without holding an open multi statement connectionon the resume/re-use path — theconnection != NULLguard is what the resume paths actually need.)Testing (PostgreSQL 18)
make build/citus_indent --checkfollow-sequence-resetfollow-data-only,cdc-endpos-between-transaction,endpos-in-multi-wal-txn,cdc-prunefollow/cli_followpath)make testsbatteryThe five standalone-
followsuites are the ones that exercisecli_follow; the endpos/resume ones specifically cover the re-use path wherestateis stale, confirming theconnection != NULLguard.