Repository navigation
[Bug] Cloud BE coordinator address matching leaks prepared transactions and blocks schema changes with FQDN #68755
Description
Search before asking
- I searched existing issues and PRs and found no duplicate for this coordinator-ID/FQDN mismatch. Related reports and fixes are listed below.
Version
Apache Doris 4.1.3
What's Wrong?
In cloud mode with FE FQDN addressing (enable_fqdn_mode), a stream-load transaction can remain in PREPARE after its coordinator BE is restarted/rescheduled. Schema-change and rollup jobs then remain in WAITING_TXN because the abandoned transaction is not recognized as belonging to the failed coordinator.
On the affected cluster, the jobs had to be unblocked by manually aborting leaked transactions. The default stream-load timeout is three days, so normal expiration can leave DDL blocked for hours or days.
There are two related identity checks:
- FE records a stream-load coordinator using the backend ID, the connection's client IP, and backend startup time.
GlobalTransactionMgr.checkFailedTxnsByCoordinator()looks up the backend by ID but additionally requiresbe.getHost().equals(coordinator.ip)before checking restart/liveness. An FQDN does not equal the recorded pod IP. Finding the backend setsoffline=false, so the address mismatch causes the method to return false despite a restart. - Meta-service
get_prepare_txn_by_coordinator()requires IP equality, andabort_txn_with_coordinator()requires both ID and IP equality. Heartbeat cleanup passes the BE host. A hostname/IP mismatch, or a changed pod IP after rescheduling, prevents matching old prepared transactions even when their backend ID is unchanged.
For example, the old transaction records (backend ID=123, IP=A, startup=T1). After rescheduling, the retained backend registration has (ID=123, hostname=be-0.example, startup=T2), with T2>T1 and a new pod IP B. The existing address checks miss the old transaction.
What You Expected?
For a retained BE registration, coordinator identity should be determined by its backend ID. A restarted or sufficiently long unavailable coordinator's abandoned transactions should be aborted automatically, allowing waiting schema-change and rollup jobs to progress.
Healthy transactions belonging to the new BE process must remain protected by startup-time filtering. Committed/final transactions must not be selected for abort, and concurrent cleanup must not cancel DDL jobs.
How to Reproduce?
Suggested controlled integration scenario (the new end-to-end scenario has not yet been run):
- Run a cloud deployment with FQDN addressing and both
enable_abort_txn_by_checking_coordinator_beandenable_abort_txn_by_checking_conflict_txnenabled. - Create a table and start a stream load. Hold it before commit so its transaction remains PREPARE; the existing
StreamLoadExecutor.commit_txn.blockdebug point intest_abort_txn_by_be.groovycan help create this state. - Start a heavyweight schema change or rollup on that table and verify WAITING_TXN.
- Restart/reschedule the coordinating BE while preserving its FQDN, heartbeat port, and FE backend registration/ID. A changed pod IP demonstrates the unstable-address case.
- Verify the BE startup time advances. Without the identity fix, the old prepared transaction is not selected by the address-based cleanup checks, and the DDL remains waiting until transaction expiration or manual abort.
A smaller deterministic meta-service reproduction is to create prepared BE transactions with ID 123 and address A, then call get_prepare_txn_by_coordinator with ID 123 and address B. Current upstream returns no matches; ID-based matching returns the old prepared transactions.
Anything Else?
Proposed fix: when both coordinator IDs are nonzero, match by backend ID; fall back to the address when an ID is unknown. In the cloud FE failed-coordinator check, remove the redundant host/IP guard after backend lookup by ID, retaining restart/liveness checks. Preserve non-cloud FE behavior.
The local patch adds a same-ID/different-IP meta-service regression case. Isolated compiled checks passed for 54 identity combinations and 33 FE failure-detection combinations. Full FE validation is running in Docker; no successful full-suite or new end-to-end result is claimed here.
Related upstream work:
- [Bug] txn prepare for 3 days , it makes alter table always in WAITING_TXN #29708 reports the same WAITING_TXN/three-day symptom but a rollback-lock-timeout cause.
- (cloud-merge) Support to abort txn when coordinate be restart and do schema change #37669 introduced heartbeat and schema-change conflict cleanup.
- [fix](fe) Keep schema change waiting on conflict txn abort failure #65196 and [fix](fe) Keep rollup jobs waiting on conflict txn abort failure #67661 protect schema-change/rollup recovery from abort failures; [fix](fe) Keep rollup jobs waiting on conflict txn abort failure #67661 also excludes committed/final transactions. These complement the identity fix.
- [fix](cloud) fix get_prepare_txn_by_coordinator method #67761 / branch-4.1: [fix](cloud) fix get_prepare_txn_by_coordinator method #67761 #68059 improve coordinator-query scan reliability and handle KV_TXN_TOO_OLD, but retain IP equality and do not fix this identity mismatch.
Are you willing to submit PR?
- Yes I am willing to submit a PR!
Code of Conduct
- I agree to follow this project's Code of Conduct.
Activity
Doris-Breakwater commentedon Oct 7, 2026
Breakwater-GitHub-Analysis-Slot: slot_ace030d334c0
Assessment: The cited upstream code confirms a coordinator-selection defect for a retained, nonzero BE ID when the transaction address differs from the registered BE host. This mechanism can explain an abandoned PREPARE transaction blocking schema change or rollup. The reported production incident and the proposed end-to-end scenario have not been independently reproduced, so this is a code-backed diagnosis under the stated conditions, not a verified deployment-wide fix.
The issue is currently open with no labels, assignee, or milestone. Suggested routing: cloud transaction management, with FE heartbeat/DDL and meta-service maintainers involved.
Verified code path
I inspected upstream master
7ac0eb2fdb426595f810e94ab77b7aa2eece12d5from the local repository and fetched the corresponding files at branch-4.178aa9c996accd114a6e0f5943d7882ee1a34011a. Both contain the reported identity predicates.TxnUtilpersists these fields into the coordinator protobuf without normalizing the IP to the registered host. Consequently, hostname/IP inequality is possible without any change in backend identity. See transaction creation and coordinator serialization.checkFailedTxnsByCoordinator()finds the BE by ID and setsoffline=false, but requires host/IP equality before evaluating restart or prolonged heartbeat loss. With the example(123, A, T1)versus(123, FQDN, T2), the address guard is false and the method returns false even whenT2>T1. This is directly established by the FE predicate, also present in branch-4.1.HeartbeatMgrsuppliesbe.getId()andbe.getHost(). In cloud mode, cleanup callsget_prepare_txn_by_coordinator(), then aborts the returned transaction IDs individually. The query requires IP equality even for matching nonzero IDs, so an address mismatch yields no candidates. The separateabort_txn_with_coordinator()RPC also requires ID and IP equality; it should receive consistent semantics, but it is not the heartbeat cleanup RPC used by this FE path. See heartbeat dispatch, cloud cleanup, and meta-service matching.Candidate fix and safety checks
The linked patch addresses both identity predicates and gates the FE behavior change on cloud mode. It is a focused change with no new configuration, RPC fields, or persisted format. Stable-ID matching should be scoped to the existing instance and retained BE registration; it does not recover an old identity after re-registration with a different ID.
coordinator.start_time < restart_start_time, and FE exclusion of COMMITTED/final transactions. The abort-by-ID handler re-reads transaction state and rejects COMMITTED/VISIBLE transactions, providing an additional protection when commit races cleanup. Preserve the existing DDL retry handling on abort failure. See abort state checks.beStartTime=0, omitting the filter. Cleanup runs on a separate single-thread executor and does not recheck BE liveness at execution. If a down task waits in the queue, the BE recovers, and a new PREPARE load starts before that task queries meta-service, ID-only selection can include the new load despite its new address/startup time. Add a deterministic delayed-down-task/recovery test and assess liveness/epoch fencing before claiming that all new-process transactions are protected. This follows from the executor and dispatch and the cloud cleanup linked above; it is not evidence that this race caused the reported incident.Evidence still needed
(source, ID, address, start_time); BE registration ID/host/startup time/liveness before and after rescheduling; DDL job ID, table, watershed transaction ID, and WAITING_TXN history. Redacted addresses should preserve equality/inequality relationships.Recommended next steps
Validation here was read-only source and public patch inspection. No Doris code was modified, and no build, native test suite, or cloud integration test was run. The reported isolated check counts are author-provided evidence, not independently verified full-system validation.
[fix](cloud) Match transaction coordinators by stable backend ID (#68756
[fix](cloud) Match transaction coordinators by stable backend ID (#68756