From 396f4d62c69335b8f7aefd43bbe099e8bb9e6905 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Thu, 10 Jan 2013 23:40:18 +0200 Subject: [PATCH] Fix for MDEV-4009: main.delayed sporadically fails with "query 'REPLACE DELAYED t1 VALUES (5)' failed: 1317: Query execution was interrupted" - Fixed broadcast without a proper mutex - Don't break existing locks if we are just testing if we can get the lock mysql-test/r/create_delayed.result: Added test case for failures with INSERT DELAYED with CREATE and DROP TABLE mysql-test/t/create_delayed.test: Added test case for failures with INSERT DELAYED with CREATE and DROP TABLE sql/mdl.cc: Don't break existing locks for timeout=0 (ie, just check if there are conflicting locks). This fixed the bug that INSERT DELAYED didn't work properly with CREATE TABLE sql/sql_base.cc: One neads to hold the mutex before doing a mysql_cond_broadcast() This fixed the bug that INSERT DELAYED didn't work properly with DROP TABLE sql/sql_insert.cc: Protect setting of mysys_var->current_mutex. --- mysql-test/r/create_delayed.result | 3 +++ mysql-test/t/create_delayed.test | 34 ++++++++++++++++++++++++++++++ sql/mdl.cc | 6 +++++- sql/sql_base.cc | 4 ++++ sql/sql_insert.cc | 4 ++++ 5 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/create_delayed.result create mode 100644 mysql-test/t/create_delayed.test diff --git a/mysql-test/r/create_delayed.result b/mysql-test/r/create_delayed.result new file mode 100644 index 00000000000..c36a8e60cbb --- /dev/null +++ b/mysql-test/r/create_delayed.result @@ -0,0 +1,3 @@ +drop table if exists t1; +Starting test +# All done diff --git a/mysql-test/t/create_delayed.test b/mysql-test/t/create_delayed.test new file mode 100644 index 00000000000..e99886d97d1 --- /dev/null +++ b/mysql-test/t/create_delayed.test @@ -0,0 +1,34 @@ +# +# Ensure that INSERT DELAYED works with CREATE TABLE on existing table +# + +-- source include/big_test.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +--disable_query_log +--disable_result_log + +--let $run=1000 + +--echo Starting test + +while ($run) +{ +# --echo # $run attempts left... + CREATE TABLE t1 ( f1 INTEGER AUTO_INCREMENT, PRIMARY KEY (f1)) ENGINE=MyISAM; + INSERT DELAYED t1 VALUES (4); +--error ER_TABLE_EXISTS_ERROR + CREATE TABLE t1 AS SELECT 1 AS f1; + + REPLACE DELAYED t1 VALUES (5); + DROP TABLE t1; +--dec $run +} + +--enable_query_log +--enable_result_log + +--echo # All done diff --git a/sql/mdl.cc b/sql/mdl.cc index 5e297051377..a2113909116 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -2078,7 +2078,11 @@ MDL_context::acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout) */ m_wait.reset_status(); - if (lock->needs_notification(ticket)) + /* + Don't break conflicting locks if timeout is 0 as 0 is used + To check if there is any conflicting locks... + */ + if (lock->needs_notification(ticket) && lock_wait_timeout) lock->notify_conflicting_locks(this); mysql_prlock_unlock(&lock->m_rwlock); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c7f93c955f3..83ed29064b5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -9299,7 +9299,11 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, in_use->killed= KILL_SYSTEM_THREAD; mysql_mutex_lock(&in_use->mysys_var->mutex); if (in_use->mysys_var->current_cond) + { + mysql_mutex_lock(in_use->mysys_var->current_mutex); mysql_cond_broadcast(in_use->mysys_var->current_cond); + mysql_mutex_unlock(in_use->mysys_var->current_mutex); + } mysql_mutex_unlock(&in_use->mysys_var->mutex); signalled= TRUE; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 231671d172b..f18a9548704 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2823,8 +2823,12 @@ pthread_handler_t handle_delayed_insert(void *arg) set_timespec(abstime, delayed_insert_timeout); /* Information for pthread_kill */ + mysql_mutex_unlock(&di->mutex); + mysql_mutex_lock(&di->thd.mysys_var->mutex); di->thd.mysys_var->current_mutex= &di->mutex; di->thd.mysys_var->current_cond= &di->cond; + mysql_mutex_unlock(&di->thd.mysys_var->mutex); + mysql_mutex_lock(&di->mutex); thd_proc_info(&(di->thd), "Waiting for INSERT"); DBUG_PRINT("info",("Waiting for someone to insert rows"));