mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
5.5-merge
This commit is contained in:
125
sql/sql_cache.cc
125
sql/sql_cache.cc
@ -334,6 +334,7 @@ TODO list:
|
||||
#include "tztime.h" // struct Time_zone
|
||||
#include "sql_acl.h" // SELECT_ACL
|
||||
#include "sql_base.h" // TMP_TABLE_KEY_EXTRA
|
||||
#include "debug_sync.h" // DEBUG_SYNC
|
||||
#ifdef HAVE_QUERY_CACHE
|
||||
#include <m_ctype.h>
|
||||
#include <my_dir.h>
|
||||
@ -342,6 +343,7 @@ TODO list:
|
||||
#include "../storage/myisammrg/myrg_def.h"
|
||||
#include "probes_mysql.h"
|
||||
#include "log_slow.h"
|
||||
#include "transaction.h"
|
||||
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
#include "emb_qcache.h"
|
||||
@ -371,42 +373,6 @@ TODO list:
|
||||
__LINE__,(ulong)(B)));B->query()->unlock_reading();}
|
||||
#define DUMP(C) DBUG_EXECUTE("qcache", {\
|
||||
(C)->cache_dump(); (C)->queries_dump();(C)->tables_dump();})
|
||||
|
||||
|
||||
/**
|
||||
Causes the thread to wait in a spin lock for a query kill signal.
|
||||
This function is used by the test frame work to identify race conditions.
|
||||
|
||||
The signal is caught and ignored and the thread is not killed.
|
||||
*/
|
||||
|
||||
static void debug_wait_for_kill(const char *info)
|
||||
{
|
||||
const char *prev_info;
|
||||
THD *thd;
|
||||
char buff[1024];
|
||||
DBUG_ENTER("debug_wait_for_kill");
|
||||
|
||||
thd= current_thd;
|
||||
prev_info= thd->proc_info;
|
||||
thd->proc_info= info;
|
||||
sql_print_information("%s", info);
|
||||
while(!thd->killed)
|
||||
my_sleep(1000);
|
||||
thd->killed= THD::NOT_KILLED;
|
||||
/*
|
||||
Remove the set debug variable, to ensure we don't get stuck on it again
|
||||
This is needed as for MyISAM, invalidate_table() may be called twice
|
||||
(Once from mysql_delete() and once from mi_update_status())
|
||||
*/
|
||||
sprintf(buff, "-d,%s", info);
|
||||
DBUG_SET(buff);
|
||||
sql_print_information("Exit debug_wait_for_kill");
|
||||
thd->proc_info= prev_info;
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
#else
|
||||
#define RW_WLOCK(M) mysql_rwlock_wrlock(M)
|
||||
#define RW_RLOCK(M) mysql_rwlock_rdlock(M)
|
||||
@ -418,6 +384,52 @@ static void debug_wait_for_kill(const char *info)
|
||||
#define DUMP(C)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
Macro that executes the requested action at a synchronization point
|
||||
only if the thread has a associated THD session.
|
||||
*/
|
||||
#if defined(ENABLED_DEBUG_SYNC)
|
||||
#define QC_DEBUG_SYNC(name) \
|
||||
do { \
|
||||
THD *thd= current_thd; \
|
||||
if (thd) \
|
||||
DEBUG_SYNC(thd, name); \
|
||||
} while (0)
|
||||
#else
|
||||
#define QC_DEBUG_SYNC(name)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
Thread state to be used when the query cache lock needs to be acquired.
|
||||
Sets the thread state name in the constructor, resets on destructor.
|
||||
*/
|
||||
|
||||
struct Query_cache_wait_state
|
||||
{
|
||||
THD *m_thd;
|
||||
const char *m_proc_info;
|
||||
|
||||
Query_cache_wait_state(THD *thd, const char *func,
|
||||
const char *file, unsigned int line)
|
||||
: m_thd(thd),
|
||||
m_proc_info(NULL)
|
||||
{
|
||||
if (m_thd)
|
||||
m_proc_info= set_thd_proc_info(m_thd,
|
||||
"Waiting for query cache lock",
|
||||
func, file, line);
|
||||
}
|
||||
|
||||
~Query_cache_wait_state()
|
||||
{
|
||||
if (m_thd)
|
||||
set_thd_proc_info(m_thd, m_proc_info, NULL, NULL, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Serialize access to the query cache.
|
||||
If the lock cannot be granted the thread hangs in a conditional wait which
|
||||
@ -439,6 +451,8 @@ static void debug_wait_for_kill(const char *info)
|
||||
bool Query_cache::try_lock(bool use_timeout)
|
||||
{
|
||||
bool interrupt= FALSE;
|
||||
THD *thd= current_thd;
|
||||
Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
|
||||
DBUG_ENTER("Query_cache::try_lock");
|
||||
|
||||
mysql_mutex_lock(&structure_guard_mutex);
|
||||
@ -448,7 +462,6 @@ bool Query_cache::try_lock(bool use_timeout)
|
||||
{
|
||||
m_cache_lock_status= Query_cache::LOCKED;
|
||||
#ifndef DBUG_OFF
|
||||
THD *thd= current_thd;
|
||||
if (thd)
|
||||
m_cache_lock_thread_id= thd->thread_id;
|
||||
#endif
|
||||
@ -507,6 +520,8 @@ bool Query_cache::try_lock(bool use_timeout)
|
||||
|
||||
void Query_cache::lock_and_suspend(void)
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
|
||||
DBUG_ENTER("Query_cache::lock_and_suspend");
|
||||
|
||||
mysql_mutex_lock(&structure_guard_mutex);
|
||||
@ -514,7 +529,6 @@ void Query_cache::lock_and_suspend(void)
|
||||
mysql_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
|
||||
m_cache_lock_status= Query_cache::LOCKED_NO_WAIT;
|
||||
#ifndef DBUG_OFF
|
||||
THD *thd= current_thd;
|
||||
if (thd)
|
||||
m_cache_lock_thread_id= thd->thread_id;
|
||||
#endif
|
||||
@ -535,6 +549,8 @@ void Query_cache::lock_and_suspend(void)
|
||||
|
||||
void Query_cache::lock(void)
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
|
||||
DBUG_ENTER("Query_cache::lock");
|
||||
|
||||
mysql_mutex_lock(&structure_guard_mutex);
|
||||
@ -542,7 +558,6 @@ void Query_cache::lock(void)
|
||||
mysql_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
|
||||
m_cache_lock_status= Query_cache::LOCKED;
|
||||
#ifndef DBUG_OFF
|
||||
THD *thd= current_thd;
|
||||
if (thd)
|
||||
m_cache_lock_thread_id= thd->thread_id;
|
||||
#endif
|
||||
@ -882,9 +897,7 @@ Query_cache::insert(Query_cache_tls *query_cache_tls,
|
||||
if (is_disabled() || query_cache_tls->first_query_block == NULL)
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
DBUG_EXECUTE_IF("wait_in_query_cache_insert",
|
||||
debug_wait_for_kill("wait_in_query_cache_insert"); );
|
||||
|
||||
QC_DEBUG_SYNC("wait_in_query_cache_insert");
|
||||
|
||||
if (try_lock())
|
||||
DBUG_VOID_RETURN;
|
||||
@ -1695,6 +1708,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
||||
}
|
||||
else
|
||||
thd->lex->safe_to_cache_query= 0; // Don't try to cache this
|
||||
/* End the statement transaction potentially started by engine. */
|
||||
trans_rollback_stmt(thd);
|
||||
goto err_unlock; // Parse query
|
||||
}
|
||||
else
|
||||
@ -1737,6 +1752,14 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
||||
thd->limit_found_rows = query->found_rows();
|
||||
thd->status_var.last_query_cost= 0.0;
|
||||
thd->query_plan_flags= (thd->query_plan_flags & ~QPLAN_QC_NO) | QPLAN_QC;
|
||||
|
||||
/*
|
||||
End the statement transaction potentially started by an
|
||||
engine callback. We ignore the return value for now,
|
||||
since as long as EOF packet is part of the query cache
|
||||
response, we can't handle it anyway.
|
||||
*/
|
||||
(void) trans_commit_stmt(thd);
|
||||
if (!thd->stmt_da->is_set())
|
||||
thd->stmt_da->disable_status();
|
||||
|
||||
@ -1786,8 +1809,7 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
|
||||
invalidate_table(thd, tables_used);
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF("wait_after_query_cache_invalidate",
|
||||
debug_wait_for_kill("wait_after_query_cache_invalidate"););
|
||||
DEBUG_SYNC(thd, "wait_after_query_cache_invalidate");
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -1978,8 +2000,7 @@ void Query_cache::flush()
|
||||
if (is_disabled())
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
DBUG_EXECUTE_IF("wait_in_query_cache_flush1",
|
||||
debug_wait_for_kill("wait_in_query_cache_flush1"););
|
||||
QC_DEBUG_SYNC("wait_in_query_cache_flush1");
|
||||
|
||||
lock_and_suspend();
|
||||
if (query_cache_size > 0)
|
||||
@ -2319,9 +2340,7 @@ void Query_cache::free_cache()
|
||||
|
||||
void Query_cache::flush_cache()
|
||||
{
|
||||
|
||||
DBUG_EXECUTE_IF("wait_in_query_cache_flush2",
|
||||
debug_wait_for_kill("wait_in_query_cache_flush2"););
|
||||
QC_DEBUG_SYNC("wait_in_query_cache_flush2");
|
||||
|
||||
my_hash_reset(&queries);
|
||||
while (queries_blocks != 0)
|
||||
@ -2767,8 +2786,7 @@ void Query_cache::invalidate_table(THD *thd, TABLE *table)
|
||||
|
||||
void Query_cache::invalidate_table(THD *thd, uchar * key, uint32 key_length)
|
||||
{
|
||||
DBUG_EXECUTE_IF("wait_in_query_cache_invalidate1",
|
||||
debug_wait_for_kill("wait_in_query_cache_invalidate1"); );
|
||||
DEBUG_SYNC(thd, "wait_in_query_cache_invalidate1");
|
||||
|
||||
/*
|
||||
Lock the query cache and queue all invalidation attempts to avoid
|
||||
@ -2776,9 +2794,7 @@ void Query_cache::invalidate_table(THD *thd, uchar * key, uint32 key_length)
|
||||
*/
|
||||
lock();
|
||||
|
||||
DBUG_EXECUTE_IF("wait_in_query_cache_invalidate2",
|
||||
debug_wait_for_kill("wait_in_query_cache_invalidate2"); );
|
||||
|
||||
DEBUG_SYNC(thd, "wait_in_query_cache_invalidate2");
|
||||
|
||||
if (query_cache_size > 0)
|
||||
invalidate_table_internal(thd, key, key_length);
|
||||
@ -2828,7 +2844,6 @@ Query_cache::invalidate_query_block_list(THD *thd,
|
||||
Query_cache_block *query_block= list_root->next->block();
|
||||
BLOCK_LOCK_WR(query_block);
|
||||
free_query(query_block);
|
||||
DBUG_EXECUTE_IF("debug_cache_locks", sleep(10););
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user