diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2018-01-12 18:17:55 +0100 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2018-01-12 18:17:55 +0100 |
commit | f26192559161143c7c0880cf24c63ced1cf9655e (patch) | |
tree | c2d1b46c6a02ecac0eeae962de854d757c1fb118 | |
parent | 5ea28015d5864bec1e44722bbc7a3d1f2371c85d (diff) | |
download | mariadb-git-bb-5.5-MDEV-14526.tar.gz |
MDEV-14526: MariaDB keeps crashing under load when query_cache_type is changedbb-5.5-MDEV-14526
The problem was in such scenatio:
T1 - starts geristering query and locked QC
T2 - starts disabling QC and wait for UNLOCK
T1 - unlock QC
T2 - disable QC and destroy sugnals without waitiung for query unlock
T1 a) - not yet unlocked query in qc and crach on attempt to unlock because QC signals are destroyed
b) if above was done before distruction, it execute end_of results first time
it exit on after try_lock which see QC disables and return TRUE.
But it do not reset query_cache_tls->first_query_block which lead to
second call of end_of_result when diagnostic arena has already inapropriate staus (not is_eof()).
Fix is:
1) wait for all queries unlocked before destroing them by locking and unlockin
2) remove query_cache_tls->first_query_block if QC disabled
-rw-r--r-- | mysql-test/r/query_cache_debug.result | 32 | ||||
-rw-r--r-- | mysql-test/t/query_cache_debug.test | 52 | ||||
-rw-r--r-- | sql/sql_cache.cc | 13 |
3 files changed, 97 insertions, 0 deletions
diff --git a/mysql-test/r/query_cache_debug.result b/mysql-test/r/query_cache_debug.result index 50a3a02fe4d..82d7d936f43 100644 --- a/mysql-test/r/query_cache_debug.result +++ b/mysql-test/r/query_cache_debug.result @@ -220,3 +220,35 @@ RESET QUERY CACHE; DROP TABLE t1; SET GLOBAL query_cache_size= DEFAULT; SET GLOBAL query_cache_type= DEFAULT; +# +# MDEV-14526: MariaDB keeps crashing under load when +# query_cache_type is changed +# +CREATE TABLE t1 ( +`id` int(10) NOT NULL AUTO_INCREMENT, +`k` int(10) NOT NULL default '0', +PRIMARY KEY (`id`)) +ENGINE=MyISAM; +INSERT IGNORE INTO t1 VALUES +(NULL,1),(NULL,8),(NULL,NULL),(NULL,NULL),(NULL,4),(NULL,9),(NULL,7), +(NULL,3),(NULL,NULL),(NULL,2),(NULL,3),(NULL,NULL),(NULL,2),(NULL,7), +(NULL,1),(NULL,2),(NULL,4),(NULL,NULL),(NULL,1),(NULL,1),(NULL,4); +Warnings: +Warning 1048 Column 'k' cannot be null +Warning 1048 Column 'k' cannot be null +Warning 1048 Column 'k' cannot be null +Warning 1048 Column 'k' cannot be null +Warning 1048 Column 'k' cannot be null +SET GLOBAL query_cache_size= 1024*1024; +SET GLOBAL query_cache_type= 1; +set debug_sync="wait_in_query_cache_store_query SIGNAL parked WAIT_FOR go"; +SELECT DISTINCT id FROM t1 WHERE id BETWEEN 5603 AND 16218 ORDER BY k; +set debug_sync="now WAIT_FOR parked"; +SET GLOBAL query_cache_type= 0; +set debug_sync="now SIGNAL go"; +id +set debug_sync= 'RESET'; +DROP TABLE t1; +SEt GLOBAL query_cache_size= DEFAULT; +SEt GLOBAL query_cache_type= DEFAULT; +# End of 5.5 tests diff --git a/mysql-test/t/query_cache_debug.test b/mysql-test/t/query_cache_debug.test index 854af85f3fb..51df5ce48da 100644 --- a/mysql-test/t/query_cache_debug.test +++ b/mysql-test/t/query_cache_debug.test @@ -319,3 +319,55 @@ RESET QUERY CACHE; DROP TABLE t1; SET GLOBAL query_cache_size= DEFAULT; SET GLOBAL query_cache_type= DEFAULT; + +--echo # +--echo # MDEV-14526: MariaDB keeps crashing under load when +--echo # query_cache_type is changed +--echo # + +CREATE TABLE t1 ( + `id` int(10) NOT NULL AUTO_INCREMENT, + `k` int(10) NOT NULL default '0', + PRIMARY KEY (`id`)) +ENGINE=MyISAM; + +INSERT IGNORE INTO t1 VALUES + (NULL,1),(NULL,8),(NULL,NULL),(NULL,NULL),(NULL,4),(NULL,9),(NULL,7), + (NULL,3),(NULL,NULL),(NULL,2),(NULL,3),(NULL,NULL),(NULL,2),(NULL,7), + (NULL,1),(NULL,2),(NULL,4),(NULL,NULL),(NULL,1),(NULL,1),(NULL,4); + +SET GLOBAL query_cache_size= 1024*1024; +SET GLOBAL query_cache_type= 1; + +--connect (con2,localhost,root,,test) +--connect (con1,localhost,root,,test) +set debug_sync="wait_in_query_cache_store_query SIGNAL parked WAIT_FOR go"; +--send + + SELECT DISTINCT id FROM t1 WHERE id BETWEEN 5603 AND 16218 ORDER BY k; + +--connection default + +set debug_sync="now WAIT_FOR parked"; +--connection con2 +--send + SET GLOBAL query_cache_type= 0; + +--connection default +set debug_sync="now SIGNAL go"; + +--connection con1 +--reap +--connection con2 +--reap + +# Cleanup +--disconnect con1 +--disconnect con2 +--connection default +set debug_sync= 'RESET'; +DROP TABLE t1; +SEt GLOBAL query_cache_size= DEFAULT; +SEt GLOBAL query_cache_type= DEFAULT; + +--echo # End of 5.5 tests diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 2ec870f314f..eb6aec8b15a 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1184,7 +1184,11 @@ void Query_cache::end_of_result(THD *thd) #endif if (try_lock(thd, Query_cache::WAIT)) + { + if (is_disabled()) + query_cache_tls->first_query_block= NULL; // do not try again with QC DBUG_VOID_RETURN; + } query_block= query_cache_tls->first_query_block; if (query_block) @@ -1556,6 +1560,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", unlock(); + DEBUG_SYNC(thd, "wait_in_query_cache_store_query"); + // init_n_lock make query block locked BLOCK_UNLOCK_WR(query_block); } @@ -2693,6 +2699,13 @@ void Query_cache::free_cache() do { Query_cache_query *query= block->query(); + /* + There will not be new requests but some maybe not finished yet, + so wait for them by trying lock/unlock + */ + BLOCK_LOCK_WR(block); + BLOCK_UNLOCK_WR(block); + mysql_rwlock_destroy(&query->lock); block= block->next; } while (block != queries_blocks); |