summaryrefslogtreecommitdiff
path: root/sql/sql_class.cc
diff options
context:
space:
mode:
authorMichael Widenius <monty@askmonty.org>2013-01-11 00:22:14 +0200
committerMichael Widenius <monty@askmonty.org>2013-01-11 00:22:14 +0200
commit6e9a48b67fceab17089ca4cd1406e302386a601b (patch)
tree41cca1d2f6ee3439b6b70e60608430164a8a8843 /sql/sql_class.cc
parent396f4d62c69335b8f7aefd43bbe099e8bb9e6905 (diff)
downloadmariadb-git-6e9a48b67fceab17089ca4cd1406e302386a601b.tar.gz
Fixed some race conditons and bugs related to killed queries
KILL now breaks locks inside InnoDB Fixed possible deadlock when running INNODB STATUS Added ha_kill_query() and kill_query() to send kill signal to all storage engines Added reset_killed() to ensure we don't reset killed state while awake() is getting called include/mysql/plugin.h: Added thd_mark_as_hard_kill() include/mysql/plugin_audit.h.pp: Added thd_mark_as_hard_kill() include/mysql/plugin_auth.h.pp: Added thd_mark_as_hard_kill() include/mysql/plugin_ftparser.h.pp: Added thd_mark_as_hard_kill() sql/handler.cc: Added ha_kill_query() to send kill signal to all storage engines sql/handler.h: Added ha_kill_query() and kill_query() to send kill signal to all storage engines sql/log_event.cc: Use reset_killed() sql/mdl.cc: use thd->killed instead of thd_killed() to abort on soft kill sql/sp_rcontext.cc: Use reset_killed() sql/sql_class.cc: Fixed possible deadlock in INNODB STATUS by not getting thd->LOCK_thd_data if it's locked. Use reset_killed() Tell storge engines that KILL has been sent sql/sql_class.h: Added reset_killed() to ensure we don't reset killed state while awake() is getting called. Added mark_as_hard_kill() sql/sql_insert.cc: Use reset_killed() sql/sql_parse.cc: Simplify detection of killed queries. Use reset_killed() sql/sql_select.cc: Use reset_killed() sql/sql_union.cc: Use reset_killed() storage/innobase/handler/ha_innodb.cc: Added innobase_kill_query() Fixed error reporting for interrupted queries. storage/xtradb/handler/ha_innodb.cc: Added innobase_kill_query() Fixed error reporting for interrupted queries.
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r--sql/sql_class.cc44
1 files changed, 30 insertions, 14 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 42952585e07..312de8c74e4 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -701,7 +701,7 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
values doesn't have to very accurate and the memory it points to is static,
but we need to attempt a snapshot on the pointer values to avoid using NULL
values. The pointer to thd->query however, doesn't point to static memory
- and has to be protected by LOCK_thread_count or risk pointing to
+ and has to be protected by thd->LOCK_thd_data or risk pointing to
uninitialized memory.
*/
const char *proc_info= thd->proc_info;
@@ -736,20 +736,21 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
str.append(proc_info);
}
- mysql_mutex_lock(&thd->LOCK_thd_data);
-
- if (thd->query())
+ /* Don't wait if LOCK_thd_data is used as this could cause a deadlock */
+ if (!mysql_mutex_trylock(&thd->LOCK_thd_data))
{
- if (max_query_len < 1)
- len= thd->query_length();
- else
- len= min(thd->query_length(), max_query_len);
- str.append('\n');
- str.append(thd->query(), len);
+ if (thd->query())
+ {
+ if (max_query_len < 1)
+ len= thd->query_length();
+ else
+ len= min(thd->query_length(), max_query_len);
+ str.append('\n');
+ str.append(thd->query(), len);
+ }
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
}
- mysql_mutex_unlock(&thd->LOCK_thd_data);
-
if (str.c_ptr_safe() == buffer)
return buffer;
@@ -1355,7 +1356,7 @@ void THD::change_user(void)
mysql_mutex_unlock(&LOCK_status);
cleanup();
- killed= NOT_KILLED;
+ reset_killed();
cleanup_done= 0;
init();
stmt_map.reset();
@@ -1610,6 +1611,10 @@ void THD::awake(killed_state state_to_set)
MYSQL_CALLBACK(scheduler, post_kill_notification, (this));
}
+ /* Interrupt target waiting inside a storage engine. */
+ if (state_to_set != NOT_KILLED)
+ ha_kill_query(this, test(state_to_set & KILL_HARD_BIT));
+
/* Broadcast a condition to kick the target if it is waiting on it. */
if (mysys_var)
{
@@ -3848,6 +3853,18 @@ extern "C" int thd_killed(const MYSQL_THD thd)
return thd->killed;
}
+/**
+ Change kill level to hard.
+ This ensures that thd_killed() will return true.
+ This is important for storage engines that uses thd_killed() to
+ verify if thread is killed.
+*/
+
+extern "C" void thd_mark_as_hard_kill(MYSQL_THD thd)
+{
+ thd->mark_as_hard_kill();
+}
+
/**
Send an out-of-band progress report to the client
@@ -5603,4 +5620,3 @@ bool Discrete_intervals_list::append(Discrete_interval *new_interval)
}
#endif /* !defined(MYSQL_CLIENT) */
-