Doris-Breakwater commented on issue #70339: URL: https://github.com/apache/doris/issues/70339#issuecomment-6680093155
Breakwater-GitHub-Analysis-Slot: slot_52a6cda8369c The reported accounting defect is supported by source inspection at **d9d60bee9fea41273206052e7eba9b331c7f9959**. This warrants triage as an FE connection-management bug: repeated identity changes can exhaust the original user's connection allowance on an FE despite its sessions having closed. The issue currently has no labels. I have not run a live Doris reproduction or verified every release branch. **Verified code path** - [`ConnectPoolMgr.registerConnection`](https://github.com/apache/doris/blob/d9d60bee9fea41273206052e7eba9b331c7f9959/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectPoolMgr.java#L116-L147) snapshots `ctx.getQualifiedUser()` for admission and increments that user's counter. It stores the mutable context in `connectionMap`, without retaining the charged username separately. - [`handleChangeUser`](https://github.com/apache/doris/blob/d9d60bee9fea41273206052e7eba9b331c7f9959/fe/fe-core/src/main/java/org/apache/doris/qe/MysqlConnectProcessor.java#L548-L578) authenticates and replaces the context's identity without adjusting connection counters. [`getQualifiedUser()`](https://github.com/apache/doris/blob/d9d60bee9fea41273206052e7eba9b331c7f9959/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java#L713-L715) derives its result from that identity. - The MySQL channel's [close listener](https://github.com/apache/doris/blob/d9d60bee9fea41273206052e7eba9b331c7f9959/fe/fe-core/src/main/java/org/apache/doris/mysql/AcceptListener.java#L112-L125) invokes [`unregisterConnection`](https://github.com/apache/doris/blob/d9d60bee9fea41273206052e7eba9b331c7f9959/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectPoolMgr.java#L169-L190), which looks up the **current** username, decrements its counter if present, and releases the global count. Thus the global count can return to zero while the original user's count remains charged. - At this revision, the refusal text is centralized in [`limitReachedMessage`](https://github.com/apache/doris/blob/d9d60bee9fea41273206052e7eba9b331c7f9959/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectPoolMgr.java#L150-L167). A per-user rejection returns the global count, so `User: 2, Current: 0` is consistent with this mechanism. The [per-user metric](https://github.com/apache/doris/blob/d9d60bee9fea41273206052e7eba9b331c7f9959/fe/fe-core/src/main/java/org/apache/doris/metric/MetricRepo.java#L483-L498) exports these same counters. **Reproduction clarification and remaining evidence** With a limit of two, two successful `u1 -> u2 -> close` cycles leave `u1` at two; the third login is then rejected. A negative `u2` count additionally requires an existing `u2` counter entry on that FE. `CREATE USER` alone does not create it in this path. For a deterministic negative-counter test, first open and close an ordinary `u2` connection on the same FE; otherwise the missing-entry check skips the decrement, while the `u1` leak still occurs. Please attach the minimal runnable client script, connector name/version, and command results, including confirmation that the identity actually changed. Pin all attempts and metric scrapes to one FE, wait for close processing, and capture that FE's per-user/global counters, an administrator process list, and the refusal log after each cycle. These establish runtime behavior; a query profile is unnecessary for this accounting path. The claim that every branch carrying #40932 is affected remains unverified and should be checked against each proposed backport target. **Suggested PR scope and validation** The proposed retained-owner approach matches the reported expectation: remember the exact username charged by a successful registration and release that reservation exactly once on removal. Keep owner bookkeeping consistent with connection publication/removal, leave no reservation after failed admission, and preserve global/Flight quota and teardown behavior in this shared pool. Update the centralized refusal formatter to expose the user's count and distinguish the rejecting quota; retain existing global and Flight diagnostics. Regression coverage should include a previously unseen target, a preinitialized target, repeated changes through several users, same-user changes, failed authentication, database-selection failure after authentication, rejected registrations, and duplicate/concurrent unregister calls. Assert that closing releases only the original reservation, counters stay nonnegative, and a fresh `u1` login succeeds after more than two completed cycles with the fix. Include the wire-protocol reproduction as well as pool-level tests. Retaining the original charge does not itself enforce the destination user's limit during `COM_CHANGE_USER`; the inspected handler has no such admission check. Treat that policy separately from balancing the existing reservation. Until a fix is deployed, using separate physical connections for different users avoids this trigger; it does not repair counters already leaked. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
