Skip to content

branch-4.1: [fix](fe) Allocate a fresh StatementContext per EXECUTE to prevent FE OOM in long-lived prepared statements - #67256 - #67926

Open
starocean999 wants to merge 3 commits into
apache:branch-4.1from
starocean999:b41_67256
Open

branch-4.1: [fix](fe) Allocate a fresh StatementContext per EXECUTE to prevent FE OOM in long-lived prepared statements - #67256#67926
starocean999 wants to merge 3 commits into
apache:branch-4.1from
starocean999:b41_67256

Conversation

@starocean999

Copy link
Copy Markdown
Contributor

pick #67256

None

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason
  • Behavior changed:

    • No.
    • Yes.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

… OOM in long-lived prepared statements (apache#67256)

Problem Summary:

A prepared statement lives as long as its connection. The
`PreparedStatementContext` kept in
`ConnectContext.preparedStatementContextMap` retains a single
`StatementContext` and reuses the same object across every `EXECUTE` for
the whole connection lifetime.

Because one object is reused across executions, its per-statement state
keeps accumulating: bound tables (`tables`, `oneLevelTables`,
`mtmvRelatedTables`, `insertTargetTables`, `viewInfos`), CTE maps,
statistics (`relationIdToStatisticsMap`, `tableIdMapping`), MV/partition
rewrite state (`mvCanRewritePartitionsMap`, `tmpPlanForMvRewrite`,
`materializationRewrittenSuccessSet`), MVCC snapshots, connector write
schemas, placeholder bindings (`idToPlaceholderRealExpr`), etc. On
long-lived connections with a high number of `EXECUTE`s, these maps only
grow and are never released until the connection closes, which can OOM
the FE.

**Root cause:** the `StatementContext` stored in
`PreparedStatementContext` was treated as a permanent
per-prepared-statement object and reused, so state that should be
per-execution lived as long as the connection.

**Fix:** instead of reusing (and clearing in place) the same
`StatementContext`, allocate a brand-new context on every `EXECUTE` and
carry over only the state that must survive between executions:

- **ID generator positions** — so ids generated during this execution
never collide with ids already present in the cached analyzed plan from
`PREPARE`;
- **placeholder real expressions** bound by the protocol layer for this
`EXECUTE` (`idToPlaceholderRealExpr`) — this is the piece that prevents
the apache#63920 parameter-mismatch regression;
- the **placeholder → comparison-slot registry** (`idToComparisonSlot`)
used by the short-circuit fast path;
- the **placeholder list**;
- the **short-circuit / nondeterministic flags** that gate the
short-circuit fast path before any re-planning.

After the swap, the previous context becomes unreachable and is promptly
GC'd, so memory no longer grows with the number of executions. The
cached analyzed plan and the point-query (short-circuit) cache live on
`PrepareCommand` and `PreparedStatementContext` respectively, so they
keep being reused across executions.

**Changes:**
- `IdGenerator`: add `getCurrentId()` so a fresh context can continue
the id generators from the previous one.
- `StatementContext`: add `createNextExecuteContext()` which allocates
the fresh context and copies over the cross-execution state above.
- `PreparedStatementContext`: add `nextStatementContext()` which swaps
in the fresh context so the old one is released.
- `ExecuteCommand`: `run()` now uses the fresh per-execution context
(and the now-redundant in-place
`resetConnectorStatementScope()`/`resetMvccSnapshots()` calls are
removed since a fresh context starts empty by construction).
- Unit tests updated to assert the fresh-context behavior
(`ExecuteCommandTest`, `ConnectorStatementScopeTest`).
None
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@starocean999

Copy link
Copy Markdown
Contributor Author

run buildall

@starocean999

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 83.33% (30/36) 🎉
Increment coverage report
Complete coverage report

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