diff options
-rw-r--r-- | include/thr_lock.h | 3 | ||||
-rw-r--r-- | mysql-test/r/delayed.result | 26 | ||||
-rw-r--r-- | mysql-test/t/delayed.test | 43 | ||||
-rw-r--r-- | mysys/thr_lock.c | 9 | ||||
-rw-r--r-- | sql/sql_insert.cc | 5 |
5 files changed, 81 insertions, 5 deletions
diff --git a/include/thr_lock.h b/include/thr_lock.h index c7754ada299..e409df30972 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -159,7 +159,8 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count); void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock); my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread); void thr_print_locks(void); /* For debugging */ -my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data); +my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, + enum thr_lock_type new_lock_type); void thr_downgrade_write_lock(THR_LOCK_DATA *data, enum thr_lock_type new_lock_type); my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data); diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index bcda6ddb6ab..4d5d656f3ce 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -284,4 +284,30 @@ ERROR 22007: Incorrect date value: '0000-00-00' for column 'f1' at row 1 INSERT DELAYED INTO t2 VALUES (0,'2007-00-00'); ERROR 22007: Incorrect date value: '2007-00-00' for column 'f1' at row 1 DROP TABLE t1,t2; +set @old_delayed_updates = @@global.low_priority_updates; +set global low_priority_updates = 1; +select @@global.low_priority_updates; +@@global.low_priority_updates +1 +drop table if exists t1; +create table t1 (a int, b int); +insert into t1 values (1,1); +lock table t1 read; +connection: update +insert delayed into t1 values (2,2);; +connection: select +select * from t1; +a b +1 1 +connection: default +select * from t1; +a b +1 1 +unlock tables; +select * from t1; +a b +1 1 +2 2 +drop table t1; +set global low_priority_updates = @old_delayed_updates; End of 5.1 tests diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test index ce57645bd4b..94ad22b80d0 100644 --- a/mysql-test/t/delayed.test +++ b/mysql-test/t/delayed.test @@ -285,4 +285,47 @@ INSERT DELAYED INTO t2 VALUES (0,'0000-00-00'); INSERT DELAYED INTO t2 VALUES (0,'2007-00-00'); DROP TABLE t1,t2; +# +# Bug#40536: SELECT is blocked by INSERT DELAYED waiting on upgrading lock, +# even with low_priority_updates +# + +set @old_delayed_updates = @@global.low_priority_updates; +set global low_priority_updates = 1; +select @@global.low_priority_updates; + +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int, b int); +insert into t1 values (1,1); +lock table t1 read; +connect (update,localhost,root,,); +connection update; +--echo connection: update +--send insert delayed into t1 values (2,2); +connection default; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where command = "Delayed insert" and state = "upgrading lock"; +--source include/wait_condition.inc +connect (select,localhost,root,,); +--echo connection: select +select * from t1; +connection default; +--echo connection: default +select * from t1; +connection default; +disconnect update; +disconnect select; +unlock tables; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where command = "Delayed insert" and state = "Waiting for INSERT"; +--source include/wait_condition.inc +select * from t1; +drop table t1; + +set global low_priority_updates = @old_delayed_updates; + --echo End of 5.1 tests diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index b13e8411771..31638ecee9a 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -1359,7 +1359,8 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, /* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */ -my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) +my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, + enum thr_lock_type new_lock_type) { THR_LOCK *lock=data->lock; DBUG_ENTER("thr_upgrade_write_delay_lock"); @@ -1372,7 +1373,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) } check_locks(lock,"before upgrading lock",0); /* TODO: Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */ - data->type=TL_WRITE; /* Upgrade lock */ + data->type= new_lock_type; /* Upgrade lock */ /* Check if someone has given us the lock */ if (!data->cond) @@ -1411,6 +1412,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) { THR_LOCK *lock=data->lock; + enum thr_lock_type write_lock_type; DBUG_ENTER("thr_reschedule_write_lock"); pthread_mutex_lock(&lock->mutex); @@ -1420,6 +1422,7 @@ my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) DBUG_RETURN(0); } + write_lock_type= data->type; data->type=TL_WRITE_DELAYED; if (lock->update_status) (*lock->update_status)(data->status_param); @@ -1438,7 +1441,7 @@ my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) free_all_read_locks(lock,0); pthread_mutex_unlock(&lock->mutex); - DBUG_RETURN(thr_upgrade_write_delay_lock(data)); + DBUG_RETURN(thr_upgrade_write_delay_lock(data, write_lock_type)); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index fb437bed3fa..fcf86edeaa9 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1690,6 +1690,7 @@ public: class Delayed_insert :public ilink { uint locks_in_memory; + thr_lock_type delayed_lock; public: THD thd; TABLE *table; @@ -1731,6 +1732,8 @@ public: pthread_cond_init(&cond_client,NULL); VOID(pthread_mutex_lock(&LOCK_thread_count)); delayed_insert_threads++; + delayed_lock= global_system_variables.low_priority_updates ? + TL_WRITE_LOW_PRIORITY : TL_WRITE; VOID(pthread_mutex_unlock(&LOCK_thread_count)); } ~Delayed_insert() @@ -2540,7 +2543,7 @@ bool Delayed_insert::handle_inserts(void) table->use_all_columns(); thd_proc_info(&thd, "upgrading lock"); - if (thr_upgrade_write_delay_lock(*thd.lock->locks)) + if (thr_upgrade_write_delay_lock(*thd.lock->locks, delayed_lock)) { /* This can happen if thread is killed either by a shutdown |