Skip to content

Physrep source log range - #6095

Open
markhannum wants to merge 2 commits into
bloomberg:mainfrom
markhannum:physrep_source_log_range
Open

Physrep source log range#6095
markhannum wants to merge 2 commits into
bloomberg:mainfrom
markhannum:physrep_source_log_range

Conversation

@markhannum

Copy link
Copy Markdown
Contributor

physrep: LSN-aware source selection to avoid no-overlap reconnect storms (DRQS 185276960)

Problem

A physical replicant that has fallen far behind (DRQS 185276960: ~2.1 GB behind)
can be handed "sources" by register_replicant that have already logdelete'd
the logs the replicant still needs. The replicant connects, discovers the
non-overlap only late — via the sentinel → truncation → sleep path — silently
retries, and repeats. In the reported incident this produced 300+ reconnects and
looked like a hang, with no operator-visible signal that no source could actually
serve the node.

Fix

Three complementary levers, designed so an upgraded binary is a behavior-neutral
drop-in and the rest can be turned on gradually.

  1. Connect-time coverage check (primary fix, ships ON).
    New physrep_source_covers_me() (bdb/phys_rep_lsn.c) probes a candidate
    source's live log range and compares it to ours before find_new_repl_db()
    commits, skipping a provably non-covering source instead of discovering it the
    slow way. It reuses the existing log-range primitives, is a purely local
    decision, and fails safe (proceeds on any probe error), so it needs neither
    the firstfile column nor a uniform fleet. Gated by
    physrep_verify_source_range (default on).

  2. Registry-side range filtering (ships OFF, via keepalive_v2).
    keepalive_v2 now reports each node's oldest log file into
    comdb2_physreps.firstfile, and register_replicant does strict
    [firstfile, file] range filtering when that column exists — with a permissive
    fallback pass so a not-yet-reporting fleet is never left with zero candidates.
    keepalive_v2 tolerates a missing firstfile column (checked via
    sys.physrep_tunables), so the binary can be deployed before the column is
    added. physrep_keepalive_v2 stays off by default so a new sender never
    invokes the v2 SP against an older metadb that cannot handle a missing column.

  3. No-viable-source alarm + observability.
    After physrep_no_source_alarm_threshold (default 10) consecutive cycles in
    which every reachable candidate was probed and none covered our LSN, the node
    latches gbl_physrep_no_viable_source, logs PHYSREP NO VIABLE SOURCE, and
    re-registers rather than spinning on a stale list. The latched state is
    exposed as the physrep_no_viable_source metric in comdb2_metrics and is
    cleared as soon as the replicant connects to a viable source (including via a
    reverse connection). The alarm only counts a cycle when no candidate was
    merely unreachable/penalized, so a transiently-down covering source does not
    misfire it.

New tunables

Tunable Default Notes
physrep_verify_source_range on Local, fail-safe connect-time check; no compatibility concerns.
physrep_keepalive_v2 off Enable fleet-wide only after the firstfile column exists.
physrep_no_source_alarm_threshold 10 Consecutive no-viable-source cycles before latching the alarm.

Recommended rollout ordering

  1. Deploy the new binary across the fleet (sources, replicants, metadbs).
    Connect-time source verification is active immediately.
  2. ALTER TABLE comdb2_physreps ADD COLUMN firstfile INT on the metadb cluster(s).
  3. Enable physrep_keepalive_v2 fleet-wide so nodes begin reporting firstfile
    and register_replicant also range-filters during registration.

Enabling physrep_keepalive_v2 before steps 1–2 are complete risks a node
invoking the v2 keepalive SP on an older metadb that cannot tolerate a missing
firstfile column. See docs/pages/operating/physical_replication.md.

Compatibility / safety

  • Behavior-neutral binary drop-in: the only default-on change is the local,
    fail-safe coverage check; all cross-node/metadb-observable behavior
    (keepalive_v2) ships off.
  • Works with or without the comdb2_physreps.firstfile column, so the column can
    be added after the binary is deployed.
  • Physrep SPs are embedded in the binary, so deploying updates them.

Testing

  • tests/phys_rep_tiered.test — added two cases (in a separate commit):
    • phys_rep_verify_tunable_defaults: asserts the tunable defaults per variant.
    • phys_rep_firstfile_rollout (FIRSTFILE=0 variants): exercises the full
      production rollout end to end — healthy with no column and keepalive_v2 off;
      enable keepalive_v2 while the column is still absent and confirm the SP
      tolerates it and keeps refreshing last_keepalive; live ALTER add the
      column on the metadbs; confirm firstfile auto-populates with no restart.
  • tests/tunables.test golden file updated for the new/changed tunable
    descriptions.
  • Built and ran the new phys_rep_tiered.test cases in isolation on a Linux
    build host.

Commits

  • physrep: LSN-aware source selection to avoid no-overlap retries (DRQS 185276960)
  • test: physrep source-range tunable defaults and firstfile rollout (DRQS 185276960)

🤖 Generated with Claude Code

@roborivers roborivers left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cbuild submission: Error ⚠.
Regression testing: Success ✓.

The first 10 failing tests are:
ssl_san
consumer_non_atomic_default_consumer_generated **quarantined**
ssl_set_cmd
ssl_prefer
ssl_dbname
sc_downgrade [timeout] **quarantined**

@roborivers roborivers left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cbuild submission: Error ⚠.
Regression testing: Success ✓.

The first 10 failing tests are:
ssl_san
consumer_non_atomic_default_consumer_generated **quarantined**
ssl_set_cmd
ssl_prefer
ssl_dbname
sc_downgrade [timeout] **quarantined**
reco-ddlk-sql [timeout] **quarantined**

markhannum and others added 2 commits July 30, 2026 11:20
… 185276960)

A lagging physical replicant whose logs fell outside a source's live log
range would repeatedly reconnect (300+ times in DRQS 185276960) to sources
that had already logdelete'd the logs it needed. The no-overlap condition
was only discovered late via the sentinel/truncation path and retried
silently, so it presented as a hang.

Three levers, all shippable as a behavior-safe gradual rollout:

1. Connect-time coverage check (primary fix, ships ON): new
   physrep_source_covers_me() in bdb/phys_rep_lsn.c probes a candidate
   source's live log range before find_new_repl_db() commits to it, and
   skips provably non-covering sources. It reuses the existing log-range
   primitives, is a purely local decision, and fails safe (proceeds on any
   probe error), so it needs neither the firstfile column nor a uniform
   fleet. Gated by physrep_verify_source_range (default on).

2. Registry-side range filtering (ships OFF via keepalive_v2): keepalive_v2
   now reports each node's oldest log file into comdb2_physreps.firstfile,
   and register_replicant does strict [firstfile, file] range filtering when
   that column exists, with a permissive fallback pass so a not-yet-reporting
   fleet is never left with zero candidates. keepalive_v2 tolerates a missing
   firstfile column (checked via sys.physrep_tunables), so the binary can be
   deployed before the column is ALTER-added. keepalive_v2 stays OFF by
   default so a new sender never invokes the v2 SP against an older metadb.

3. No-viable-source alarm: after physrep_no_source_alarm_threshold (default
   10) consecutive cycles where a source was reached but none covered our
   LSN, latch gbl_physrep_no_viable_source and log "PHYSREP NO VIABLE
   SOURCE"; re-register between passes rather than spinning on a stale list.

Documents the rollout ordering (deploy binary -> ALTER add firstfile ->
enable keepalive_v2) in physical_replication.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Mark Hannum <mhannum@bloomberg.net>
…QS 185276960)

Add two cases to phys_rep_tiered.test:

- phys_rep_verify_tunable_defaults: asserts physrep_verify_source_range
  defaults ON and physrep_no_source_alarm_threshold defaults 10, and that
  physrep_keepalive_v2 is OFF by default (ON in the firstfile variant).

- phys_rep_firstfile_rollout (FIRSTFILE=0 variants only): exercises the
  production rollout end to end -- healthy with no firstfile column and
  keepalive_v2 off; enable keepalive_v2 while the column is still absent and
  confirm the SP tolerates it and keeps refreshing last_keepalive; live ALTER
  add the firstfile column on the metadbs; confirm keepalive_v2 auto-populates
  firstfile with no restart. Runs last since it mutates tunables and schema.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Mark Hannum <mhannum@bloomberg.net>
@markhannum
markhannum force-pushed the physrep_source_log_range branch from 0952a46 to 4e73c3e Compare July 30, 2026 15:20

@roborivers roborivers left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cbuild submission: Error ⚠.
Regression testing: Success ✓.

The first 10 failing tests are:
consumer_non_atomic_default_consumer_generated **quarantined**
sc_downgrade [timeout] **quarantined**
reco-ddlk-sql [timeout] **quarantined**

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants