Skip to content

MDEV-41243, MDEV-41273 Don't freeze mem_root after engine pushdown - #5783

Open
bsrikanth-mariadb wants to merge 1 commit into
13.2-MDEV-39226-direct-multi_table-update-deletefrom
13.2-MDEV-41243-fedx-pushdown-assert-for-upd-del-prepared-stmts
Open

bsrikanth-mariadb wants to merge 1 commit into
13.2-MDEV-39226-direct-multi_table-update-deletefrom
13.2-MDEV-41243-fedx-pushdown-assert-for-upd-del-prepared-stmts

Conversation

@bsrikanth-mariadb

@bsrikanth-mariadb bsrikanth-mariadb commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

When a statement is pushed down to an engine, the once-per-statement
part of the optimization (e.g. the first_cond_optimization part of
JOIN::optimize(), or the whole of JOIN::optimize() for a pushed down
UNION) is skipped. Re-executing the same prepared statement or stored
routine without pushdown then allocated from a mem_root already marked
ROOT_FLAG_READ_ONLY, hitting an assertion in alloc_root().

Add LEX::dont_freeze_mem_root, set by the pushdown_handler and
derived_handler constructors so it covers every engine implementing
them. Prepared_statement::execute_loop(), sp_head::execute() (through
sp_head::dont_freeze_mem_root) and the SP instruction reparse path no
longer freeze the mem_root of such statements. The flag is only
declared and used in PROTECT_STATEMENT_MEMROOT builds.

The flag is per execution for prepared statements:
Prepared_statement::execute_loop() clears it after each execution, so
the mem_root is frozen again after the first later execution that is
not pushed down. For a stored routine the instruction's LEX keeps the
flag, so once one instruction has been pushed down the routine's
mem_root stays unfrozen, even if later executions are not pushed down,
unless the routine is re-parsed into a new LEX.

Add tests for prepared SELECT, UNION, UPDATE and DELETE, prepared
EXPLAIN of a pushed UNION, derived tables, stored procedures,
functions, triggers, cursors and metadata-invalidation reparse, with
pushdown switched on and off. Most prepared statement and routine
tests check the statements received by the remote server, or EXPLAIN,
to verify that pushdown actually happened.

@bsrikanth-mariadb
bsrikanth-mariadb force-pushed the 13.2-MDEV-41243-fedx-pushdown-assert-for-upd-del-prepared-stmts branch 2 times, most recently from 437d6a6 to 5072028 Compare October 5, 2026 04:45
@bsrikanth-mariadb bsrikanth-mariadb changed the title MDEV-41243, MDEV-41273: update, delete, select prepared statements assert with fedx_pushdown MDEV-41243, MDEV-41273 Don't freeze mem_root after engine pushdown Oct 5, 2026
@spetrunia

Copy link
Copy Markdown
Member

@bsrikanth-mariadb , questions for you:

Add LEX::dont_freeze_mem_root, set by the pushdown_handler and
derived_handler constructors so it covers every engine implementing
them. Prepared_statement::execute_loop(), sp_head::execute() (through
sp_head::dont_freeze_mem_root) and the SP instruction reparse path no
longer freeze the mem_root of such statements. The flag is only
declared and used in PROTECT_STATEMENT_MEMROOT builds.
...
For a stored routine one
pushed down instruction disables it for the whole routine.

Can you elaborate why is that? I assume individual statements in SP may use derived_pushdown. But don't they have their own LEX and lex->mem_root ?

Note this disables the mem_root protection for the statement for good,
even if later executions are not pushed down.

Why? What if we clear dont_freeze_mem_root after every execution? Would that work?

@spetrunia

Copy link
Copy Markdown
Member

( Note to self: attempt to set LEX::dont_freeze_mem_root at the point where the derived or select_handler is actually used has shown that we'd need to set it in 5 places. Too many)

@bsrikanth-mariadb

Copy link
Copy Markdown
Contributor Author

@bsrikanth-mariadb , questions for you:

Add LEX::dont_freeze_mem_root, set by the pushdown_handler and
derived_handler constructors so it covers every engine implementing
them. Prepared_statement::execute_loop(), sp_head::execute() (through
sp_head::dont_freeze_mem_root) and the SP instruction reparse path no
longer freeze the mem_root of such statements. The flag is only
declared and used in PROTECT_STATEMENT_MEMROOT builds.
...
For a stored routine one
pushed down instruction disables it for the whole routine.

Can you elaborate why is that? I assume individual statements in SP may use derived_pushdown. But don't they have their own LEX and lex->mem_root ?

Note this disables the mem_root protection for the statement for good,
even if later executions are not pushed down.

Why? What if we clear dont_freeze_mem_root after every execution? Would that work?

After a statement's first successful execution, its mem_root is marked ROOT_FLAG_READ_ONLY, and it it can't be unfreezed right (even if we turn of dont_freeze_mem_root flag)?

@bsrikanth-mariadb
bsrikanth-mariadb force-pushed the 13.2-MDEV-41243-fedx-pushdown-assert-for-upd-del-prepared-stmts branch 2 times, most recently from 59db312 to caa187c Compare October 8, 2026 13:13
@CLAassistant

CLAassistant commented Oct 8, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@bsrikanth-mariadb
bsrikanth-mariadb force-pushed the 13.2-MDEV-41243-fedx-pushdown-assert-for-upd-del-prepared-stmts branch 4 times, most recently from 71a4be6 to e7d8301 Compare October 12, 2026 02:25
When a statement is pushed down to an engine, the once-per-statement
part of the optimization (e.g. the first_cond_optimization part of
JOIN::optimize(), or the whole of JOIN::optimize() for a pushed down
UNION) is skipped. Re-executing the same prepared statement or stored
routine without pushdown then allocated from a mem_root already marked
ROOT_FLAG_READ_ONLY, hitting an assertion in alloc_root().

Add LEX::dont_freeze_mem_root, set by the pushdown_handler and
derived_handler constructors so it covers every engine implementing
them. Prepared_statement::execute_loop(), sp_head::execute() (through
sp_head::dont_freeze_mem_root) and the SP instruction reparse path no
longer freeze the mem_root of such statements. The flag is only
declared and used in PROTECT_STATEMENT_MEMROOT builds.

The flag is per execution for prepared statements:
Prepared_statement::execute_loop() clears it after each execution, so
the mem_root is frozen again after the first later execution that is
not pushed down. For a stored routine the instruction's LEX keeps the
flag, so once one instruction has been pushed down the routine's
mem_root stays unfrozen, even if later executions are not pushed down,
unless the routine is re-parsed into a new LEX.

Add tests for prepared SELECT, UNION, UPDATE and DELETE, prepared
EXPLAIN of a pushed UNION, derived tables, stored procedures,
functions, triggers, cursors and metadata-invalidation reparse, with
pushdown switched on and off. Most prepared statement and routine
tests check the statements received by the remote server, or EXPLAIN,
to verify that pushdown actually happened.
@bsrikanth-mariadb
bsrikanth-mariadb force-pushed the 13.2-MDEV-41243-fedx-pushdown-assert-for-upd-del-prepared-stmts branch from e7d8301 to 999b11b Compare October 21, 2026 04:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

4 participants