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

More query cache optimizations

- Added query_cache_type == ALWAYS_OFF to turn of query cache permanently
  for new open tables. Without this option storage engines has to call
  query cache for all update querys and invalidate used tables that has
  a small overhead. When running benchmarks without query cache, this
  is the option to use!
- Updated MyISAM, Aria, MYISAM_MRG and InnoDB to support ALWAYS_OFF.
- Setting query_cache_size in a config file will not automatically enable
  the query cache.
- Added query_cache_available() that functions can check if query cache
  can be used or if it is permanently disabled.
- Moved things around in Query_cache::store_query() to get more work done
  outside of query cache mutex.
- Same for Query_cache::send_result_to_client()

Co-author: Thirunarayanan Balathandayuthapani <thiru@mariadb.com>
- ÌnnoDB changes reviewed and improved
This commit is contained in:
Monty
2026-09-11 18:14:14 +03:00
parent 8b8adddb29
commit be5ee0e3d5
23 changed files with 207 additions and 110 deletions

View File

@@ -1229,7 +1229,8 @@ The following specify which files/extra groups are read (specified before remain
SQL_CACHE' at start of query (to avoid locks that ON and
DEMAND have to take). TABLES = Cache only queries marked
with SQL_CACHE or queries where all tables are created
with SQL_CACHE=1
with SQL_CACHE=1. ALWAYS_OFF = query cache is permanently
OFF and cannot be enabled
--query-cache-wlock-invalidate
Invalidate queries in query cache on LOCK for write
--query-prealloc-size=#

View File

@@ -1 +1,2 @@
--query-cache-size=1355776
--query-cache-type=ON

View File

@@ -1,3 +1,6 @@
select @@query_cache_type;
@@query_cache_type
ON
set @sql_mode_save=@@global.sql_mode;
set @query_cache_type_save=@@global.query_cache_type;
set @query_cache_size_save=@@global.query_cache_size;

View File

@@ -5,6 +5,7 @@
#
# Tests with query cache
#
select @@query_cache_type;
set @sql_mode_save=@@global.sql_mode;
set @query_cache_type_save=@@global.query_cache_type;
set @query_cache_size_save=@@global.query_cache_size;

View File

@@ -99,8 +99,8 @@ SELECT @@global.query_cache_type;
DEMAND
SET @@global.query_cache_type = 0.4;
ERROR 42000: Incorrect argument type to variable 'query_cache_type'
SET @@global.query_cache_type = 5;
ERROR 42000: Variable 'query_cache_type' can't be set to the value of '5'
SET @@global.query_cache_type = 6;
ERROR 42000: Variable 'query_cache_type' can't be set to the value of '6'
'#---------------------FN_DYNVARS_134_08----------------------#'
SET @@global.query_cache_type = TRUE;
SELECT @@global.query_cache_type;
@@ -120,11 +120,24 @@ SET global query_cache_type = 0;
SELECT @@global.query_cache_type;
@@global.query_cache_type
OFF
SET @@global.query_cache_type = @global_start_value;
SET global query_cache_type = ON;
SELECT @@global.query_cache_type;
@@global.query_cache_type
ON
SET @@query_cache_type = ALWAYS_OFF;
select @@query_cache_type;
@@query_cache_type
OFF
SET @@session.query_cache_type = @session_start_value;
SELECT @@session.query_cache_type;
@@session.query_cache_type
SET @@query_cache_type= ON;
SET @@global.query_cache_type = ALWAYS_OFF;
SELECT @@global.query_cache_type;
@@global.query_cache_type
ALWAYS_OFF
select @@query_cache_type;
@@query_cache_type
OFF
SET @@global.query_cache_type = ON;
ERROR HY000: Query cache is globally disabled and you can't enable it only for this session
SET @@session.query_cache_type = ON;
ERROR HY000: Query cache is globally disabled and you can't enable it only for this session
# restart

View File

@@ -3375,11 +3375,11 @@ COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME QUERY_CACHE_TYPE
VARIABLE_SCOPE SESSION
VARIABLE_TYPE ENUM
VARIABLE_COMMENT OFF = Don't cache or retrieve results. ON = Cache all results except for queries marked with SQL_NO_CACHE. DEMAND = Cache only queries marked with SQL_CACHE. DEMAND_STRICT = Like DEMAND but only check for 'SELECT SQL_CACHE' at start of query (to avoid locks that ON and DEMAND have to take). TABLES = Cache only queries marked with SQL_CACHE or queries where all tables are created with SQL_CACHE=1
VARIABLE_COMMENT OFF = Don't cache or retrieve results. ON = Cache all results except for queries marked with SQL_NO_CACHE. DEMAND = Cache only queries marked with SQL_CACHE. DEMAND_STRICT = Like DEMAND but only check for 'SELECT SQL_CACHE' at start of query (to avoid locks that ON and DEMAND have to take). TABLES = Cache only queries marked with SQL_CACHE or queries where all tables are created with SQL_CACHE=1. ALWAYS_OFF = query cache is permanently OFF and cannot be enabled
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON,DEMAND,DEMAND_STRICT,TABLES
ENUM_VALUE_LIST OFF,ON,DEMAND,DEMAND_STRICT,TABLES,ALWAYS_OFF
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME QUERY_CACHE_WLOCK_INVALIDATE

View File

@@ -3625,11 +3625,11 @@ COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME QUERY_CACHE_TYPE
VARIABLE_SCOPE SESSION
VARIABLE_TYPE ENUM
VARIABLE_COMMENT OFF = Don't cache or retrieve results. ON = Cache all results except for queries marked with SQL_NO_CACHE. DEMAND = Cache only queries marked with SQL_CACHE. DEMAND_STRICT = Like DEMAND but only check for 'SELECT SQL_CACHE' at start of query (to avoid locks that ON and DEMAND have to take). TABLES = Cache only queries marked with SQL_CACHE or queries where all tables are created with SQL_CACHE=1
VARIABLE_COMMENT OFF = Don't cache or retrieve results. ON = Cache all results except for queries marked with SQL_NO_CACHE. DEMAND = Cache only queries marked with SQL_CACHE. DEMAND_STRICT = Like DEMAND but only check for 'SELECT SQL_CACHE' at start of query (to avoid locks that ON and DEMAND have to take). TABLES = Cache only queries marked with SQL_CACHE or queries where all tables are created with SQL_CACHE=1. ALWAYS_OFF = query cache is permanently OFF and cannot be enabled
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON,DEMAND,DEMAND_STRICT,TABLES
ENUM_VALUE_LIST OFF,ON,DEMAND,DEMAND_STRICT,TABLES,ALWAYS_OFF
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME QUERY_CACHE_WLOCK_INVALIDATE

View File

@@ -161,7 +161,7 @@ SELECT @@global.query_cache_type;
SET @@global.query_cache_type = 0.4;
--Error ER_WRONG_VALUE_FOR_VAR
SET @@global.query_cache_type = 5;
SET @@global.query_cache_type = 6;
--echo '#---------------------FN_DYNVARS_134_08----------------------#'
@@ -187,15 +187,27 @@ SELECT @@query_cache_type;
SET global query_cache_type = 0;
SELECT @@global.query_cache_type;
##############################
# Restore initial value #
##############################
################################
# Change value permanently #
################################
SET @@global.query_cache_type = @global_start_value;
SET global query_cache_type = ON;
SELECT @@global.query_cache_type;
SET @@session.query_cache_type = @session_start_value;
SELECT @@session.query_cache_type;
SET @@query_cache_type = ALWAYS_OFF;
select @@query_cache_type;
SET @@query_cache_type= ON;
SET @@global.query_cache_type = ALWAYS_OFF;
SELECT @@global.query_cache_type;
select @@query_cache_type;
--error ER_QUERY_CACHE_IS_GLOBALY_DISABLED
SET @@global.query_cache_type = ON;
--error ER_QUERY_CACHE_IS_GLOBALY_DISABLED
SET @@session.query_cache_type = ON;
--source include/restart_mysqld.inc
########################################################################
# END OF query_cache_type TESTS #

View File

@@ -5148,12 +5148,6 @@ static int init_server_components()
query_cache_set_min_res_unit(query_cache_min_res_unit);
query_cache_result_size_limit(query_cache_limit);
/* if we set size of QC non zero in config then probably we want it ON */
if (query_cache_size != 0 &&
global_system_variables.query_cache_type == QUERY_CACHE_TYPE_OFF &&
!IS_SYSVAR_AUTOSIZE(&query_cache_size))
{
global_system_variables.query_cache_type= QUERY_CACHE_TYPE_ON;
}
query_cache_init();
DBUG_ASSERT(query_cache_size < ULONG_MAX);
query_cache_resize((ulong)query_cache_size);

View File

@@ -571,9 +571,10 @@ insert_space:
@param thd thread handle
*/
void inline fix_local_query_cache_mode(THD *thd)
void fix_local_query_cache_mode(THD *thd)
{
if (global_system_variables.query_cache_type == QUERY_CACHE_TYPE_OFF)
if (global_system_variables.query_cache_type == QUERY_CACHE_TYPE_OFF ||
global_system_variables.query_cache_type == QUERY_CACHE_TYPE_ALWAYS_OFF)
thd->variables.query_cache_type= QUERY_CACHE_TYPE_OFF;
}
@@ -1285,6 +1286,16 @@ void mysql_query_cache_invalidate4(THD *thd,
query_cache.invalidate(thd, key, (uint32) key_length, (my_bool) using_trx);
}
extern "C"
{
/* Return 1 if query cache is on or could be enabled later */
my_bool query_cache_available()
{
return (global_system_variables.query_cache_type !=
QUERY_CACHE_TYPE_ALWAYS_OFF);
}
}
/*****************************************************************************
Query_cache methods
@@ -1361,13 +1372,14 @@ size_t Query_cache::resize(size_t query_cache_size_arg)
will not be reflected on global_system_variables.query_cache_type
*/
if (new_query_cache_size &&
global_system_variables.query_cache_type != QUERY_CACHE_TYPE_OFF)
global_system_variables.query_cache_type != QUERY_CACHE_TYPE_OFF &&
global_system_variables.query_cache_type != QUERY_CACHE_TYPE_ALWAYS_OFF)
{
DBUG_EXECUTE("check_querycache",check_integrity(1););
m_cache_status= OK; // size > 0 => enable cache
m_cache_status= OK; // size > 0 => resize cache
}
else
m_cache_status= DISABLED; // size 0 means the cache disabled
m_cache_status= DISABLED; // size 0 means the cache disabled
unlock();
DBUG_RETURN(new_query_cache_size);
@@ -1424,7 +1436,6 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
}
#endif //EMBEDDED_LIBRARY
/* The following assert fails if we haven't called send_result_to_client */
DBUG_ASSERT(thd->base_query.is_alloced() ||
thd->base_query.ptr() == thd->query());
@@ -1498,33 +1509,6 @@ def_week_frmt: %zu, in_trans: %d, autocommit: %d",
(int)flags.in_trans,
(int)flags.autocommit));
/*
A table- or a full flush operation can potentially take a long time to
finish. We choose not to wait for them and skip caching statements
instead.
In case the wait time can't be determined there is an upper limit which
causes try_lock() to abort with a time out.
The 'TIMEOUT' parameter indicate that the lock is allowed to timeout
*/
if (try_lock(thd, Query_cache::TIMEOUT))
DBUG_VOID_RETURN;
if (query_cache_size == 0)
{
unlock();
DBUG_VOID_RETURN;
}
DUMP(this);
if (ask_handler_allowance(thd, tables_used))
{
refused++;
unlock();
DBUG_VOID_RETURN;
}
query= thd->base_query.ptr();
query_length= thd->base_query.length();
@@ -1549,6 +1533,34 @@ def_week_frmt: %zu, in_trans: %d, autocommit: %d",
memcpy((void*) (query + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
&flags, QUERY_CACHE_FLAGS_SIZE);
/*
A table- or a full flush operation can potentially take a long time to
finish. We choose not to wait for them and skip caching statements
instead.
In case the wait time can't be determined there is an upper limit which
causes try_lock() to abort with a time out.
The 'TIMEOUT' parameter indicate that the lock is allowed to timeout
*/
if (try_lock(thd, Query_cache::TIMEOUT))
DBUG_VOID_RETURN;
if (query_cache_size == 0) // Recheck under lock
{
unlock();
DBUG_VOID_RETURN;
}
DUMP(this);
if (ask_handler_allowance(thd, tables_used))
{
refused++;
unlock();
DBUG_VOID_RETURN;
}
/* Check if another thread is processing the same query? */
Query_cache_block *competitor = (Query_cache_block *)
my_hash_search(&queries, (uchar*) query, tot_length);
@@ -1913,21 +1925,6 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
goto err;
}
}
/*
Try to obtain an exclusive lock on the query cache. If the cache is
disabled or if a full cache flush is in progress, the attempt to
get the lock is aborted.
The TIMEOUT parameter indicate that the lock is allowed to timeout.
*/
if (try_lock(thd, Query_cache::TIMEOUT))
goto err;
if (query_cache_size == 0)
{
thd->query_cache_is_applicable= 0; // Query can't be cached
goto err_unlock;
}
Query_cache_block *query_block;
if (thd->variables.query_cache_strip_comments)
@@ -1961,8 +1958,6 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
DBUG_PRINT("qcache", ("No active database"));
}
THD_STAGE_INFO(thd, stage_checking_query_cache_for_query);
// fill all gaps between fields with 0 to get repeatable key
bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
flags.client_long_flag= MY_TEST(thd->client_capabilities & CLIENT_LONG_FLAG);
@@ -2019,6 +2014,24 @@ def_week_frmt: %zu, in_trans: %d, autocommit: %d",
memcpy((uchar *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
(uchar*) &flags, QUERY_CACHE_FLAGS_SIZE);
/*
Try to obtain an exclusive lock on the query cache. If the cache is
disabled or if a full cache flush is in progress, the attempt to
get the lock is aborted.
The TIMEOUT parameter indicate that the lock is allowed to timeout.
*/
if (try_lock(thd, Query_cache::TIMEOUT))
goto err;
if (query_cache_size == 0)
{
thd->query_cache_is_applicable= 0; // Query can't be cached
goto err_unlock;
}
THD_STAGE_INFO(thd, stage_checking_query_cache_for_query);
#ifdef WITH_WSREP
bool once_more;
once_more= true;
@@ -2617,7 +2630,8 @@ void Query_cache::init()
time. This is because we want to avoid locking the QC specific
mutex if query cache isn't going to be used.
*/
if (global_system_variables.query_cache_type == QUERY_CACHE_TYPE_OFF)
if (global_system_variables.query_cache_type == QUERY_CACHE_TYPE_OFF ||
global_system_variables.query_cache_type == QUERY_CACHE_TYPE_ALWAYS_OFF)
{
m_cache_status= DISABLE_REQUEST;
free_cache();
@@ -4093,8 +4107,8 @@ void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
are defined with SQL_CACHE=1
RETURN
0 error
>0 number of tables
0 error.
>0 number of tables ; *tables_type is up to date
Notes:
MERGE TABLE childs are not tested for SQL_CACHE=1.
@@ -4139,8 +4153,7 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
{
DBUG_PRINT("qcache", ("Don't cache statement as it refers to "
"tables with column privileges."));
thd->query_cache_is_applicable= 0; // Query can't be cached
thd->lex->safe_to_cache_query= 0; // For prepared statements
goto not_cacheable;
DBUG_RETURN(0);
}
#endif
@@ -4167,27 +4180,34 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
table->s->table_name.str,
table->s->db.str,
table->s->db_type()->db_type));
if (table->s->table_category != TABLE_CATEGORY_USER ||
table->s->query_cache == HA_CHOICE_NO)
goto not_cacheable;
cache_type= table->file->table_cache_type();
*tables_type|= cache_type;
table_count+= table->file->count_query_cache_dependant_tables(tables_type);
if ((no_cache= ((cache_type & HA_CACHE_TBL_NOCACHE) ||
table->s->table_category != TABLE_CATEGORY_USER ||
table->s->query_cache == HA_CHOICE_NO)) ||
if ((no_cache= (cache_type & HA_CACHE_TBL_NOCACHE)) ||
(only_sqlcache_tables && table->s->query_cache != HA_CHOICE_YES))
{
DBUG_PRINT("qcache",
("select not cacheable: temporary, system or "
"other non-cacheable table(s)"));
thd->query_cache_is_applicable= 0; // Query can't be cached
/* For prepared statements */
if (no_cache)
thd->lex->safe_to_cache_query= 0;
thd->query_cache_is_applicable= 0; // Query can't be cached
DBUG_RETURN(0);
}
}
DBUG_RETURN(table_count);
not_cacheable:
thd->lex->safe_to_cache_query= 0; // For prepared statements
thd->query_cache_is_applicable= 0; // Query can't be cached
DBUG_RETURN(0);
}

View File

@@ -55,6 +55,7 @@ typedef struct st_changed_table_list CHANGED_TABLE_LIST;
#define QUERY_CACHE_TYPE_DEMAND 2
#define QUERY_CACHE_TYPE_DEMAND_STRICT 3
#define QUERY_CACHE_TYPE_TABLES 4
#define QUERY_CACHE_TYPE_ALWAYS_OFF 5
/* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */
#define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4
@@ -265,6 +266,7 @@ extern "C"
my_bool);
const uchar *query_cache_table_get_key(const void *record, size_t *length,
my_bool);
my_bool query_cache_available();
}
extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename);
@@ -580,7 +582,6 @@ struct Query_cache_query_flags
};
#define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags)
#define QUERY_CACHE_DB_LENGTH_SIZE 2
#include "sql_cache.h"
#define query_cache_abort(A,B) query_cache.abort(A,B)
#define query_cache_end_of_result(A) query_cache.end_of_result(A)
#define query_cache_store_query(A, B) query_cache.store_query(A, B)
@@ -601,6 +602,8 @@ struct Query_cache_query_flags
#define query_cache_is_cacheable_query(L) \
(((L)->sql_command == SQLCOM_SELECT) && (L)->safe_to_cache_query)
extern void fix_local_query_cache_mode(THD *thd);
/* See also sql_class.h for some inline query cache functions */
extern MYSQL_PLUGIN_IMPORT Query_cache query_cache;

View File

@@ -1442,6 +1442,7 @@ void THD::init()
backup_commit_lock= 0;
num_of_strings_sorted_on_truncated_length= 0;
query_cache_is_applicable= 0;
fix_local_query_cache_mode(this);
#ifdef WITH_WSREP
wsrep_last_query_id= 0;
wsrep_xid.null();

View File

@@ -3542,27 +3542,43 @@ static Sys_var_ulong Sys_query_cache_min_res_unit(
ON_UPDATE(fix_qcache_min_res_unit));
static const char *query_cache_type_names[]=
{ "OFF", "ON", "DEMAND", "DEMAND_STRICT", "TABLES", 0};
{ "OFF", "ON", "DEMAND", "DEMAND_STRICT", "TABLES", "ALWAYS_OFF", NullS};
static bool check_query_cache_type(sys_var *self, THD *thd, set_var *var)
{
int global_query_cache_type= global_system_variables.query_cache_type;
if (query_cache.is_disable_in_progress())
{
my_error(ER_QUERY_CACHE_IS_DISABLED, MYF(0));
return true;
}
if (var->type != OPT_GLOBAL &&
global_system_variables.query_cache_type == QUERY_CACHE_TYPE_OFF)
if (global_query_cache_type == QUERY_CACHE_TYPE_ALWAYS_OFF)
{
if (var->value)
my_error(ER_QUERY_CACHE_IS_GLOBALY_DISABLED, MYF(0));
return true;
}
if (var->type != OPT_GLOBAL)
{
if (global_query_cache_type == QUERY_CACHE_TYPE_OFF ||
global_query_cache_type == QUERY_CACHE_TYPE_ALWAYS_OFF)
{
if (var->save_result.ulonglong_value != 0)
if (var->value)
{
my_error(ER_QUERY_CACHE_IS_GLOBALY_DISABLED, MYF(0));
return true;
if (var->save_result.ulonglong_value != 0)
{
my_error(ER_QUERY_CACHE_IS_GLOBALY_DISABLED, MYF(0));
return true;
}
}
}
else if (var->value &&
var->save_result.ulonglong_value == QUERY_CACHE_TYPE_ALWAYS_OFF)
{
/* session should never be QUERY_CACHE_TYPE_ALWAYS_OFF */
var->save_result.ulonglong_value= QUERY_CACHE_TYPE_OFF;
}
}
return false;
}
@@ -3573,7 +3589,8 @@ static bool fix_query_cache_type(sys_var *self, THD *thd, enum_var_type type)
if (type != OPT_GLOBAL)
return false;
if (global_system_variables.query_cache_type != QUERY_CACHE_TYPE_OFF)
if (global_system_variables.query_cache_type != QUERY_CACHE_TYPE_OFF &&
global_system_variables.query_cache_type != QUERY_CACHE_TYPE_ALWAYS_OFF)
{
if (query_cache.is_disabled())
{
@@ -3596,7 +3613,8 @@ static Sys_var_enum Sys_query_cache_type(
"DEMAND_STRICT = Like DEMAND but only check for 'SELECT SQL_CACHE' "
"at start of query (to avoid locks that ON and DEMAND have to take). "
"TABLES = Cache only queries marked with SQL_CACHE or queries where all "
"tables are created with SQL_CACHE=1",
"tables are created with SQL_CACHE=1. "
"ALWAYS_OFF = query cache is permanently OFF and cannot be enabled",
NO_SET_STMT SESSION_VAR(query_cache_type), CMD_LINE(REQUIRED_ARG),
query_cache_type_names, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(check_query_cache_type),

View File

@@ -150,6 +150,7 @@ dict_table_t *dict_table_t::create(const span<const char> &name,
table->name.m_name= mem_strdupl(name.data(), name.size());
table->mdl_name.m_name= table->name.m_name;
table->is_system_db= dict_mem_table_is_system(table->name.m_name);
table->query_cache= query_cache_available();
table->space= space;
table->space_id= space ? space->id : UINT32_MAX;
table->n_t_cols= static_cast<unsigned>(n_cols + DATA_N_SYS_COLS) &

View File

@@ -3047,6 +3047,25 @@ static void innodb_ahi_enable(dict_table_t *innodb_table,
}
#endif
/** Copy the query cache usage flag from MariaDB table definition.
Query is never cached if it uses that is not plain user table
(temporary table) or that was created with SQL_CACHE=0
@param innodb_table InnoDB table
@param table MariaDB table definition */
static void innobase_copy_query_cache_flag(dict_table_t *innodb_table,
const TABLE *table) noexcept
{
const bool query_cache= table->s->query_cache != HA_CHOICE_NO &&
!innodb_table->is_temporary() && query_cache_available();
if (query_cache && !innodb_table->query_cache)
{
innodb_table->query_cache_inv_trx_id= trx_sys.get_max_trx_id();
innodb_table->query_cache= query_cache;
}
}
/*********************************************************************//**
Copy table flags from MySQL's HA_CREATE_INFO into an InnoDB table object.
Those flags are stored in .frm file and end up in the MySQL table object,
@@ -3068,6 +3087,7 @@ innobase_copy_frm_flags_from_create_info(
innodb_ahi_enable(innodb_table, create_info->option_struct, table);
#endif
}
innobase_copy_query_cache_flag(innodb_table, table);
}
/**
@@ -3090,6 +3110,7 @@ void innobase_copy_frm_flags_from_table(dict_table_t *innodb_table,
innodb_ahi_enable(innodb_table, table_share->option_struct_table, table);
#endif
}
innobase_copy_query_cache_flag(innodb_table, table);
}
/*********************************************************************//**

View File

@@ -2521,6 +2521,7 @@ public:
/*!< True if the table belongs to a system
database (mysql, information_schema or
performance_schema) */
bool query_cache; /* 1 if query cache is in use */
dict_frm_t dict_frm_mismatch;
/*!< !DICT_FRM_CONSISTENT==0 if data
dictionary information and
@@ -2695,7 +2696,8 @@ public:
/** Timestamp of the last modification of this table. */
Atomic_relaxed<time_t> update_time;
/** Transactions whose view low limit is greater than this number are
not allowed to access the MariaDB query cache.
not allowed to access the MariaDB query cache. Maintained while
query_cache is set
@see innobase_query_caching_table_check_low()
@see trx_t::commit_tables() */
Atomic_relaxed<trx_id_t> query_cache_inv_trx_id;

View File

@@ -1022,7 +1022,8 @@ row_ins_foreign_check_on_constraint(
the mutex rank above the lock_sys.latch. The query cache mutex
has a rank just above the lock_sys.latch. */
row_ins_invalidate_query_cache(thr, table->name.m_name);
if (table->query_cache)
row_ins_invalidate_query_cache(thr, table->name.m_name);
node = static_cast<upd_node_t*>(thr->run_node);

View File

@@ -1313,13 +1313,15 @@ inline void trx_t::commit_tables()
{
if (undo_no && !mod_tables.empty())
{
const trx_id_t max_trx_id= trx_sys.get_max_trx_id();
trx_id_t max_trx_id= 0;
const auto now= start_time;
for (const auto &p : mod_tables)
{
dict_table_t *table= p.first;
table->update_time= now;
if (!table->query_cache) continue;
if (!max_trx_id) max_trx_id= trx_sys.get_max_trx_id();
table->query_cache_inv_trx_id= max_trx_id;
}
}

View File

@@ -1151,8 +1151,8 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked)
}
if (aria_readonly)
file->s->options|= HA_OPTION_READ_ONLY_DATA;
file->s->chst_invalidator= query_cache_invalidate_by_MyISAM_filename_ref;
if (table->s->query_cache != HA_CHOICE_NO && query_cache_available())
file->s->chst_invalidator= query_cache_invalidate_by_MyISAM_filename_ref;
/* Set external_ref, mainly for temporary tables */
file->external_ref= (void*) table; // For ma_killed()
@@ -3108,10 +3108,10 @@ static void reset_thd_trn(THD *thd, MARIA_HA *first_table)
If table has changed by this statement, invalidate it from the query
cache
*/
if (table->row_changes != table->start_row_changes)
if (table->s->chst_invalidator &&
table->row_changes != table->start_row_changes)
{
table->start_row_changes= table->row_changes;
DBUG_ASSERT(table->s->chst_invalidator != NULL);
(*table->s->chst_invalidator)(table->s->data_file_name.str);
}
}

View File

@@ -334,11 +334,12 @@ void _ma_update_status(void* param)
DBUG_ASSERT(!info->s->base.born_transactional);
share->state.state= *info->state;
info->state= &share->state.state;
DBUG_PRINT("info", ("invalidator... '%s' (status update)",
info->s->data_file_name.str));
DBUG_ASSERT(info->s->chst_invalidator != NULL);
(*info->s->chst_invalidator)((const char *)info->s->data_file_name.str);
if (info->s->chst_invalidator)
{
DBUG_PRINT("info", ("invalidator... '%s' (status update)",
info->s->data_file_name.str));
(*info->s->chst_invalidator)((const char *)info->s->data_file_name.str);
}
}
info->append_insert_at_end= 0;
}

View File

@@ -813,7 +813,8 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
return (my_errno ? my_errno : -1);
file->s->chst_invalidator= query_cache_invalidate_by_MyISAM_filename_ref;
if (table->s->query_cache != HA_CHOICE_NO && query_cache_available())
file->s->chst_invalidator= query_cache_invalidate_by_MyISAM_filename_ref;
/* Set external_ref, mainly for temporary tables */
file->external_ref= (void*) table; // For mi_killed()

View File

@@ -335,8 +335,8 @@ void mi_update_status(void* param)
info->s->state.state= *info->state;
DBUG_PRINT("info", ("invalidator... '%s' (status update)",
info->filename));
DBUG_ASSERT(info->s->chst_invalidator != NULL);
(*info->s->chst_invalidator)((const char *)info->filename);
if (info->s->chst_invalidator)
(*info->s->chst_invalidator)((const char *)info->filename);
}
info->state= &info->s->state.state;

View File

@@ -832,7 +832,8 @@ int ha_myisammrg::attach_children(void)
goto err;
}
DBUG_PRINT("myrg", ("calling myrg_extrafunc"));
myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
if (query_cache_available())
myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
myrg_extra(file,HA_EXTRA_NO_WAIT_LOCK,0);