1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

[No MDEV#] Do not start context recorder if querying I_S tables.

This allows to record and save both Optimizer Context and Trace with
straightforward command sequence:

set optimizer_record_context=1, optimizer_trace=1;
explain select ... ;
select context from information_schema.optimizer_context;
select trace from information_schema.optimizer_trace;
This commit is contained in:
Sergei Petrunia
2026-06-01 13:45:12 +03:00
parent 5ac6071462
commit a9c8e722d8
7 changed files with 79 additions and 5 deletions

View File

@@ -426,4 +426,34 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL btn NULL NULL NULL 4 Using where
set optimizer_replay_context='';
drop table t1;
#
#
#
create table t1 (a varchar(32));
insert into t1 values ('aaaaaa'),('bbbbbb');
#
# Test 1: Reading optimizer context preserves optimizer trace:
#
set optimizer_record_context=1, optimizer_trace=1;
explain select * from t1 where a >'foo' or a < 'bar';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
select context like '%bar%' from information_schema.optimizer_context;
context like '%bar%'
1
select trace like '%foo%' from information_schema.optimizer_trace;
trace like '%foo%'
1
#
# Test 2: Reading optimizer trace preserves optimizer context:
#
explain select * from t1 where a >'foo' or a < 'bar';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
select trace like '%foo%' from information_schema.optimizer_trace;
trace like '%foo%'
1
select context like '%bar%' from information_schema.optimizer_context;
context like '%bar%'
1
drop database db1;

View File

@@ -203,4 +203,27 @@ set optimizer_replay_context='';
--remove_file "$MYSQLTEST_VARDIR/tmp/dump1.sql"
drop table t1;
--echo #
--echo #
--echo #
create table t1 (a varchar(32));
insert into t1 values ('aaaaaa'),('bbbbbb');
--echo #
--echo # Test 1: Reading optimizer context preserves optimizer trace:
--echo #
set optimizer_record_context=1, optimizer_trace=1;
explain select * from t1 where a >'foo' or a < 'bar';
select context like '%bar%' from information_schema.optimizer_context;
select trace like '%foo%' from information_schema.optimizer_trace;
--echo #
--echo # Test 2: Reading optimizer trace preserves optimizer context:
--echo #
explain select * from t1 where a >'foo' or a < 'bar';
select trace like '%foo%' from information_schema.optimizer_trace;
select context like '%bar%' from information_schema.optimizer_context;
drop database db1;

View File

@@ -19,8 +19,8 @@
#include "opt_context_store_replay.h"
#include "sql_show.h"
#include "my_json_writer.h"
#include "mysql.h"
#include "hash.h"
#include "opt_trace.h"
#include "sql_select.h"
#include "sql_explain.h"
@@ -1486,13 +1486,19 @@ void init_optimizer_context_replay_if_needed(THD *thd)
}
}
void init_optimizer_context_recorder_if_needed(THD *thd)
void init_optimizer_context_recorder_if_needed(THD *thd,
const TABLE_LIST *query_tables)
{
if (thd->spcont)
{
/* This is a sub-statement inside SP. Don't do anything */
return;
}
/* Do not record queries that query I_S.OPTIMIZER_{TRACE,CONTEXT} tables */
if (list_has_optimizer_trace_table(query_tables))
return;
if (!thd->variables.optimizer_record_context)
{
clean_captured_ctx(thd);

View File

@@ -33,7 +33,8 @@ class Range_print_enumerator;
class table_context_for_store;
class Multi_range_read_const_call_record;
void init_optimizer_context_recorder_if_needed(THD *thd);
void init_optimizer_context_recorder_if_needed(THD *thd,
const TABLE_LIST *query_tables);
/*
Recorder is used to capture the environment during query optimization run.

View File

@@ -29,6 +29,9 @@
const Lex_ident_i_s_table I_S_table_name= "OPTIMIZER_TRACE"_Lex_ident_i_s_table;
const Lex_ident_i_s_table I_S_opt_context_table_name=
"OPTIMIZER_CONTEXT"_Lex_ident_i_s_table;
/**
Whether a list of tables contains information_schema.OPTIMIZER_TRACE.
@param tbl list of tables
@@ -38,13 +41,22 @@ const Lex_ident_i_s_table I_S_table_name= "OPTIMIZER_TRACE"_Lex_ident_i_s_table;
the OPTIMIZER_TRACE table. So using a stored routine or view to read
OPTIMIZER_TRACE will overwrite OPTIMIZER_TRACE as it runs and provide
uninteresting info.
Also, return true if the query reads from I_S.OPTIMIZER_CONTEXT. This
will handle this sequence:
Q1: <query>
Q2: select * from information_schema.optimizer_context;
Q3: select * from information_schema.optimizer_trace;
Here, Q2 should not overwrite the optimizer trace left by Q1.
*/
bool list_has_optimizer_trace_table(const TABLE_LIST *tbl)
{
for (; tbl; tbl= tbl->next_global)
{
if (tbl->schema_table &&
I_S_table_name.streq(tbl->schema_table->table_name))
(I_S_table_name.streq(tbl->schema_table->table_name) ||
I_S_opt_context_table_name.streq(tbl->schema_table->table_name)))
return true;
}
return false;

View File

@@ -226,6 +226,8 @@ void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp);
*/
int fill_optimizer_trace_info(THD *thd, TABLE_LIST *tables, Item *);
bool list_has_optimizer_trace_table(const TABLE_LIST *tbl);
#define OPT_TRACE_TRANSFORM(thd, object_level0, object_level1, \
select_number, from, to) \
Json_writer_object object_level0(thd); \

View File

@@ -3560,7 +3560,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
thd->last_sql_command= lex->sql_command;
init_optimizer_context_replay_if_needed(thd);
init_optimizer_context_recorder_if_needed(thd);
init_optimizer_context_recorder_if_needed(thd, all_tables);
/*
Reset warning count for each query that uses tables