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]

Reply via email to