mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 21:42:35 +01:00
664bb23a30
The problem is that select queries executed concurrently with a concurrent insert on a MyISAM table could be cached if the select started after the query cache invalidation but before the unlock of tables performed by the concurrent insert. This race could happen because the concurrent insert was failing to prevent cache of select queries happening at the same time. The solution is to add a 'uncacheable' status flag to signal that a concurrent insert is being performed on the table and that queries executing at the same time shouldn't cache the results. mysql-test/r/query_cache_debug.result: Add test case result for Bug#41098 mysql-test/t/disabled.def: Re-enable test case. mysql-test/t/query_cache_debug.test: Add test case for Bug#41098 sql/sql_cache.cc: Debug sync point for regression testing purposes. sql/sql_insert.cc: Remove meaningless query cache invalidate. There is already a preceding invalidate for queries that started before the concurrent insert. storage/myisam/ha_myisam.cc: Check for a active concurrent insert. storage/myisam/mi_locking.c: Signal the start of a concurrent insert. Flag is zeroed once the state is updated back. storage/myisam/myisamdef.h: Add flag to signal a active concurrent insert.
114 lines
3.4 KiB
Text
114 lines
3.4 KiB
Text
--source include/not_embedded.inc
|
|
--source include/have_query_cache.inc
|
|
--source include/have_debug.inc
|
|
|
|
#
|
|
# Bug #30887 Server crashes on SET GLOBAL query_cache_size=0
|
|
#
|
|
flush status;
|
|
set query_cache_type=DEMAND;
|
|
set global query_cache_size= 1024*768;
|
|
--disable_warnings
|
|
drop table if exists t1;
|
|
--enable_warnings
|
|
create table t1 (a varchar(100));
|
|
insert into t1 values ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
|
|
connect (bug30887con1, localhost, root, ,test);
|
|
connect (bug30887con2, localhost, root, ,test);
|
|
|
|
connection bug30887con1;
|
|
--echo Activate debug hook and attempt to retrieve the statement from the cache.
|
|
set session debug='+d,wait_in_query_cache_insert';
|
|
--send select SQL_CACHE * from t1;
|
|
|
|
connection default;
|
|
let $wait_condition= select count(*)= 1 from information_schema.processlist where state= 'wait_in_query_cache_insert';
|
|
--source include/wait_condition.inc
|
|
|
|
connection bug30887con2;
|
|
--echo On a second connection; clear the query cache.
|
|
show status like 'Qcache_queries_in_cache';
|
|
set global query_cache_size= 0;
|
|
|
|
connection default;
|
|
--echo Signal the debug hook to release the lock.
|
|
select id from information_schema.processlist where state='wait_in_query_cache_insert' into @thread_id;
|
|
kill query @thread_id;
|
|
|
|
--echo Show query cache status.
|
|
show status like 'Qcache_queries_in_cache';
|
|
|
|
disconnect bug30887con1;
|
|
disconnect bug30887con2;
|
|
set global query_cache_size= 0;
|
|
use test;
|
|
drop table t1;
|
|
|
|
#
|
|
# Bug#41098: Query Cache returns wrong result with concurrent insert
|
|
#
|
|
|
|
SET @old_concurrent_insert= @@GLOBAL.concurrent_insert;
|
|
SET @old_query_cache_size= @@GLOBAL.query_cache_size;
|
|
|
|
--disable_warnings
|
|
DROP TABLE IF EXISTS t1, t2;
|
|
--enable_warnings
|
|
CREATE TABLE t1 (a INT);
|
|
CREATE TABLE t2 (a INT);
|
|
INSERT INTO t1 VALUES (1),(2),(3);
|
|
|
|
SET GLOBAL concurrent_insert= 1;
|
|
SET GLOBAL query_cache_size= 1024*512;
|
|
SET GLOBAL query_cache_type= ON;
|
|
|
|
connect(con1,localhost,root,,test,,);
|
|
connect(con2,localhost,root,,test,,);
|
|
|
|
connection con1;
|
|
--echo # Switch to connection con1
|
|
SET SESSION debug='+d,wait_after_query_cache_invalidate';
|
|
--echo # Send concurrent insert, will wait in the query cache table invalidate
|
|
--send INSERT INTO t1 VALUES (4)
|
|
|
|
connection default;
|
|
--echo # Switch to connection default
|
|
--echo # Wait for concurrent insert to reach the debug point
|
|
let $wait_condition=
|
|
SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
|
WHERE STATE = "wait_after_query_cache_invalidate" AND
|
|
INFO = "INSERT INTO t1 VALUES (4)";
|
|
--source include/wait_condition.inc
|
|
|
|
connection con2;
|
|
--echo # Switch to connection con2
|
|
--echo # Send SELECT that shouldn't be cached
|
|
SELECT * FROM t1;
|
|
|
|
connection default;
|
|
--echo # Switch to connection default
|
|
--echo # Notify the concurrent insert to proceed
|
|
SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST
|
|
WHERE STATE = 'wait_after_query_cache_invalidate' INTO @thread_id;
|
|
KILL QUERY @thread_id;
|
|
|
|
connection con1;
|
|
--echo # Switch to connection con1
|
|
--echo # Gather insert result
|
|
--reap
|
|
SHOW STATUS LIKE "Qcache_queries_in_cache";
|
|
--echo # Test that it's cacheable
|
|
SELECT * FROM t1;
|
|
SHOW STATUS LIKE "Qcache_queries_in_cache";
|
|
|
|
--echo # Disconnect
|
|
disconnect con1;
|
|
disconnect con2;
|
|
|
|
connection default;
|
|
--echo # Restore defaults
|
|
RESET QUERY CACHE;
|
|
DROP TABLE t1,t2;
|
|
SET GLOBAL concurrent_insert= DEFAULT;
|
|
SET GLOBAL query_cache_size= DEFAULT;
|
|
SET GLOBAL query_cache_type= DEFAULT;
|