mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
- Fix for Bug#40179 Test main.query_cache failing randomly on Pushbuild, test weakness
- disable the test suffering from Bug#41098 Query Cache returns wrong result with concurrent insert - additional improvements Details: - Move the test for the historic bug Bug 28249 Query Cache returns wrong result with concurrent insert / certain lock into its own testscript query_cache_28249.test. - query_cache.test: - replace error numbers with error names - remove trailing spaces, replace tabs with spaces - reset of @@global.log_bin_trust_function_creators to its original value at the end of the test - query_cache_28249.test: - replace sleep 5 with poll routine - avoid random differences caused by concurrent_inserts effects - improved comments and formatting
This commit is contained in:
@ -1116,12 +1116,13 @@ create procedure `p1`()
|
||||
begin
|
||||
select a, f1() from t1;
|
||||
end//
|
||||
SET @log_bin_trust_function_creators = @@global.log_bin_trust_function_creators;
|
||||
SET GLOBAL log_bin_trust_function_creators = 1;
|
||||
call p1()//
|
||||
a f1()
|
||||
1 2
|
||||
2 2
|
||||
SET GLOBAL log_bin_trust_function_creators = 0;
|
||||
SET GLOBAL log_bin_trust_function_creators = @log_bin_trust_function_creators;
|
||||
drop procedure p1//
|
||||
drop function f1//
|
||||
drop table t1//
|
||||
@ -1615,41 +1616,6 @@ id
|
||||
DROP PROCEDURE proc29856;
|
||||
DROP TABLE t1;
|
||||
SET GLOBAL query_cache_size= default;
|
||||
Bug#28249 Query Cache returns wrong result with concurrent insert/ certain lock
|
||||
set GLOBAL query_cache_type=1;
|
||||
set GLOBAL query_cache_limit=10000;
|
||||
set GLOBAL query_cache_min_res_unit=0;
|
||||
set GLOBAL query_cache_size= 100000;
|
||||
flush tables;
|
||||
drop table if exists t1, t2;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
Locking table T2 with a write lock.
|
||||
lock table t2 write;
|
||||
Select blocked by write lock.
|
||||
select *, (select count(*) from t2) from t1;;
|
||||
Sleeing is ok, because selecting should be done very fast.
|
||||
Inserting into table T1.
|
||||
insert into t1 values (4);
|
||||
Unlocking the tables.
|
||||
unlock tables;
|
||||
Collecting result from previously blocked select.
|
||||
Next select should contain 4 rows, as the insert is long finished.
|
||||
select *, (select count(*) from t2) from t1;
|
||||
a (select count(*) from t2)
|
||||
1 0
|
||||
2 0
|
||||
3 0
|
||||
4 0
|
||||
reset query cache;
|
||||
select *, (select count(*) from t2) from t1;
|
||||
a (select count(*) from t2)
|
||||
1 0
|
||||
2 0
|
||||
3 0
|
||||
4 0
|
||||
drop table t1,t2;
|
||||
#
|
||||
# Bug#25132 disabled query cache: Qcache_free_blocks = 1
|
||||
#
|
||||
|
62
mysql-test/r/query_cache_28249.result
Normal file
62
mysql-test/r/query_cache_28249.result
Normal file
@ -0,0 +1,62 @@
|
||||
SET @query_cache_type= @@global.query_cache_type;
|
||||
SET @query_cache_limit= @@global.query_cache_limit;
|
||||
SET @query_cache_min_res_unit= @@global.query_cache_min_res_unit;
|
||||
SET @query_cache_size= @@global.query_cache_size;
|
||||
# Bug#28249 Query Cache returns wrong result with concurrent insert/ certain lock
|
||||
# Establish connections user1,user2,user3 (user=root)
|
||||
# Switch to connection user1
|
||||
SET GLOBAL query_cache_type=1;
|
||||
SET GLOBAL query_cache_limit=10000;
|
||||
SET GLOBAL query_cache_min_res_unit=0;
|
||||
SET GLOBAL query_cache_size= 100000;
|
||||
FLUSH TABLES;
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TABLE t2 (a INT);
|
||||
INSERT INTO t1 VALUES (1),(2),(3);
|
||||
# Switch to connection user2
|
||||
LOCK TABLE t2 WRITE;
|
||||
# Switch to connection user1
|
||||
# "send" the next select, "reap" the result later.
|
||||
# The select will be blocked by the write lock on the t1.
|
||||
SELECT *, (SELECT COUNT(*) FROM t2) FROM t1;
|
||||
# Switch to connection user3
|
||||
# Poll till the select of connection user1 is blocked by the write lock on t1.
|
||||
SELECT user,command,state,info FROM information_schema.processlist
|
||||
WHERE state = 'Locked'
|
||||
AND info = 'SELECT *, (SELECT COUNT(*) FROM t2) FROM t1';
|
||||
user command state info
|
||||
root Query Locked SELECT *, (SELECT COUNT(*) FROM t2) FROM t1
|
||||
INSERT INTO t1 VALUES (4);
|
||||
# Switch to connection user2
|
||||
UNLOCK TABLES;
|
||||
# Switch to connection user1
|
||||
# Collecting ("reap") the result from the previously blocked select.
|
||||
# The printing of the result (varies between 3 and 4 rows) set has to be suppressed.
|
||||
# Switch to connection user3
|
||||
# The next select enforces that effects of "concurrent_inserts" like the
|
||||
# record with a = 4 is missing in result sets can no more happen.
|
||||
SELECT 1 FROM t1 WHERE a = 4;
|
||||
1
|
||||
1
|
||||
# Switch to connection user1
|
||||
# The next result set must contain 4 rows.
|
||||
SELECT *, (SELECT COUNT(*) FROM t2) FROM t1;
|
||||
a (SELECT COUNT(*) FROM t2)
|
||||
1 0
|
||||
2 0
|
||||
3 0
|
||||
4 0
|
||||
RESET QUERY CACHE;
|
||||
SELECT *, (SELECT COUNT(*) FROM t2) FROM t1;
|
||||
a (SELECT COUNT(*) FROM t2)
|
||||
1 0
|
||||
2 0
|
||||
3 0
|
||||
4 0
|
||||
DROP TABLE t1,t2;
|
||||
# Switch to connection default + close connections user1,user2,user3
|
||||
SET GLOBAL query_cache_type= @query_cache_type;
|
||||
SET GLOBAL query_cache_limit= @query_cache_limit;
|
||||
SET GLOBAL query_cache_min_res_unit= @query_cache_min_res_unit;
|
||||
SET GLOBAL query_cache_size= @query_cache_size;
|
@ -12,3 +12,4 @@
|
||||
federated_transactions : Bug#29523 Transactions do not work
|
||||
log_tables.test : Bug #37798: main.log_tables fails randomly on powermacg5 and windows
|
||||
slow_query_log_func.test : Bug #37962: *_func tests containing sleeps/race conditions
|
||||
query_cache_28249 : Bug#41098 Query Cache returns wrong result with concurrent insert
|
||||
|
@ -300,7 +300,7 @@ select * from t1;
|
||||
select * from t1;
|
||||
show status like "Qcache_queries_in_cache";
|
||||
insert delayed into t1 values (4);
|
||||
--sleep 5 # Wait for insert delayed to be executed.
|
||||
--sleep 5 # Wait for insert delayed to be executed.
|
||||
select a from t1;
|
||||
show status like "Qcache_queries_in_cache";
|
||||
drop table t1;
|
||||
@ -410,10 +410,10 @@ create table t1(id int auto_increment primary key);
|
||||
insert into t1 values (NULL), (NULL), (NULL);
|
||||
select * from t1 where id=2;
|
||||
alter table t1 rename to t2;
|
||||
-- error 1146
|
||||
--error ER_NO_SUCH_TABLE
|
||||
select * from t1 where id=2;
|
||||
drop table t2;
|
||||
-- error 1146
|
||||
--error ER_NO_SUCH_TABLE
|
||||
select * from t1 where id=2;
|
||||
|
||||
#
|
||||
@ -435,7 +435,7 @@ create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
show status like "Qcache_queries_in_cache";
|
||||
select * from t1 into outfile "query_cache.out.file";
|
||||
--error 1086
|
||||
--error ER_FILE_EXISTS_ERROR
|
||||
select * from t1 into outfile "query_cache.out.file";
|
||||
select * from t1 limit 1 into dumpfile "query_cache.dump.file";
|
||||
show status like "Qcache_queries_in_cache";
|
||||
@ -537,7 +537,7 @@ drop table t1;
|
||||
# If at least one of the above variables has changed,
|
||||
# the cached query can't be reused. In the below test
|
||||
# absolutely the same query is used several times,
|
||||
# SELECT should fetch different results for every instance.
|
||||
# SELECT should fetch different results for every instance.
|
||||
# No hits should be produced.
|
||||
# New cache entry should appear for every SELECT.
|
||||
#
|
||||
@ -554,21 +554,21 @@ show status like "Qcache_queries_in_cache";
|
||||
# Change collation_connection and run the same query again
|
||||
#
|
||||
set collation_connection=koi8r_bin;
|
||||
SELECT a,'<27>','<27>'='<27>' FROM t1;
|
||||
SELECT a,'<27>','<27>'='<27>' FROM t1;
|
||||
show status like "Qcache_hits";
|
||||
show status like "Qcache_queries_in_cache";
|
||||
#
|
||||
# Now change character_set_client and run the same query again
|
||||
#
|
||||
set character_set_client=cp1251;
|
||||
SELECT a,'<27>','<27>'='<27>' FROM t1;
|
||||
SELECT a,'<27>','<27>'='<27>' FROM t1;
|
||||
show status like "Qcache_hits";
|
||||
show status like "Qcache_queries_in_cache";
|
||||
#
|
||||
# And finally change character_set_results and run the same query again
|
||||
#
|
||||
set character_set_results=cp1251;
|
||||
SELECT a,'<27>','<27>'='<27>' FROM t1;
|
||||
SELECT a,'<27>','<27>'='<27>' FROM t1;
|
||||
show status like "Qcache_hits";
|
||||
show status like "Qcache_queries_in_cache";
|
||||
SET NAMES default;
|
||||
@ -602,12 +602,12 @@ insert into t1 set c = repeat('x',24);
|
||||
insert into t1 set c = concat(repeat('x',24),'x');
|
||||
insert into t1 set c = concat(repeat('x',24),'w');
|
||||
insert into t1 set c = concat(repeat('x',24),'y');
|
||||
set max_sort_length=200;
|
||||
set max_sort_length=200;
|
||||
select c from t1 order by c, id;
|
||||
reset query cache;
|
||||
set max_sort_length=20;
|
||||
select c from t1 order by c, id;
|
||||
set max_sort_length=200;
|
||||
set max_sort_length=200;
|
||||
select c from t1 order by c, id;
|
||||
set max_sort_length=default;
|
||||
# sql_mode
|
||||
@ -801,9 +801,10 @@ create procedure `p1`()
|
||||
begin
|
||||
select a, f1() from t1;
|
||||
end//
|
||||
SET @log_bin_trust_function_creators = @@global.log_bin_trust_function_creators;
|
||||
SET GLOBAL log_bin_trust_function_creators = 1;
|
||||
call p1()//
|
||||
SET GLOBAL log_bin_trust_function_creators = 0;
|
||||
SET GLOBAL log_bin_trust_function_creators = @log_bin_trust_function_creators;
|
||||
drop procedure p1//
|
||||
drop function f1//
|
||||
|
||||
@ -1016,7 +1017,7 @@ set GLOBAL query_cache_size= default;
|
||||
|
||||
|
||||
#
|
||||
# Bug #28897 UUID() returns non-unique values when query cache is enabled
|
||||
# Bug#28897 UUID() returns non-unique values when query cache is enabled
|
||||
#
|
||||
|
||||
set GLOBAL query_cache_size=1000000;
|
||||
@ -1025,7 +1026,7 @@ create table t1 (a char);
|
||||
insert into t1 values ('c');
|
||||
|
||||
let $q1= `select UUID(), a from t1`;
|
||||
let $q2= `select UUID(), a from t1`;
|
||||
let $q2= `select UUID(), a from t1`;
|
||||
|
||||
# disabling the logging of the query because the UUIDs are different each run.
|
||||
--disable_query_log
|
||||
@ -1046,7 +1047,7 @@ create table t1 (a char);
|
||||
insert into t1 values ('c');
|
||||
|
||||
let $q1= `select RAND() from t1 union select sql_cache 1 from t1;`;
|
||||
let $q2= `select RAND() from t1 union select sql_cache 1 from t1;`;
|
||||
let $q2= `select RAND() from t1 union select sql_cache 1 from t1;`;
|
||||
|
||||
# disabling the logging of the query because the times are different each run.
|
||||
--disable_query_log
|
||||
@ -1181,75 +1182,6 @@ DROP PROCEDURE proc29856;
|
||||
DROP TABLE t1;
|
||||
SET GLOBAL query_cache_size= default;
|
||||
|
||||
#
|
||||
# Bug #28249 Query Cache returns wrong result with concurrent insert / certain lock
|
||||
#
|
||||
--echo Bug#28249 Query Cache returns wrong result with concurrent insert/ certain lock
|
||||
connect (user1,localhost,root,,test,,);
|
||||
connect (user2,localhost,root,,test,,);
|
||||
connect (user3,localhost,root,,test,,);
|
||||
|
||||
connection user1;
|
||||
|
||||
set GLOBAL query_cache_type=1;
|
||||
set GLOBAL query_cache_limit=10000;
|
||||
set GLOBAL query_cache_min_res_unit=0;
|
||||
set GLOBAL query_cache_size= 100000;
|
||||
|
||||
flush tables;
|
||||
--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);
|
||||
connection user2;
|
||||
--echo Locking table T2 with a write lock.
|
||||
lock table t2 write;
|
||||
|
||||
connection user1;
|
||||
--echo Select blocked by write lock.
|
||||
--send select *, (select count(*) from t2) from t1;
|
||||
--echo Sleeing is ok, because selecting should be done very fast.
|
||||
sleep 5;
|
||||
|
||||
connection user3;
|
||||
--echo Inserting into table T1.
|
||||
insert into t1 values (4);
|
||||
|
||||
connection user2;
|
||||
--echo Unlocking the tables.
|
||||
unlock tables;
|
||||
|
||||
connection user1;
|
||||
--echo Collecting result from previously blocked select.
|
||||
#
|
||||
# Since the lock ordering rule in thr_multi_lock depends on
|
||||
# pointer values, from execution to execution we might have
|
||||
# different lock order, and therefore, sometimes lock t1 and block
|
||||
# on t2, and sometimes block on t2 right away. In the second case,
|
||||
# the following insert succeeds, and only then this select can
|
||||
# proceed, and we actually test nothing, as the very first select
|
||||
# returns 4 rows right away.
|
||||
# It's fine to have a test case that covers the problematic area
|
||||
# at least once in a while.
|
||||
# We, however, need to disable the result log here to make the
|
||||
# test repeatable.
|
||||
--disable_result_log
|
||||
--reap
|
||||
--enable_result_log
|
||||
--echo Next select should contain 4 rows, as the insert is long finished.
|
||||
select *, (select count(*) from t2) from t1;
|
||||
reset query cache;
|
||||
select *, (select count(*) from t2) from t1;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
connection default;
|
||||
disconnect user1;
|
||||
disconnect user2;
|
||||
disconnect user3;
|
||||
|
||||
#
|
||||
--echo #
|
||||
--echo # Bug#25132 disabled query cache: Qcache_free_blocks = 1
|
||||
@ -1260,7 +1192,7 @@ set global query_cache_type=0;
|
||||
show status like 'Qcache_free_blocks';
|
||||
|
||||
--echo Restore default values.
|
||||
# Bug #28211 RENAME DATABASE and query cache don't play nicely together
|
||||
# Bug#28211 RENAME DATABASE and query cache don't play nicely together
|
||||
#
|
||||
# TODO: enable these tests when RENAME DATABASE is implemented.
|
||||
# --disable_warnings
|
||||
@ -1278,7 +1210,7 @@ show status like 'Qcache_free_blocks';
|
||||
# show status like 'Qcache_queries_in_cache';
|
||||
# drop database db2;
|
||||
# set global query_cache_size=default;
|
||||
#
|
||||
#
|
||||
# --disable_warnings
|
||||
# drop database if exists db1;
|
||||
# drop database if exists db3;
|
||||
|
124
mysql-test/t/query_cache_28249.test
Normal file
124
mysql-test/t/query_cache_28249.test
Normal file
@ -0,0 +1,124 @@
|
||||
### t/query_cache_28249.test ###
|
||||
#
|
||||
# Test for
|
||||
# Bug #28249 Query Cache returns wrong result with concurrent insert / certain lock
|
||||
#
|
||||
# Last modification:
|
||||
# 2008-11-27 mleich - Move this test out of query_cache.test
|
||||
# - Fix Bug#40179 Test main.query_cache failing randomly on Pushbuild,
|
||||
# test weakness
|
||||
# - Minor improvements (comments,formatting etc.)
|
||||
#
|
||||
|
||||
--source include/have_query_cache.inc
|
||||
|
||||
SET @query_cache_type= @@global.query_cache_type;
|
||||
SET @query_cache_limit= @@global.query_cache_limit;
|
||||
SET @query_cache_min_res_unit= @@global.query_cache_min_res_unit;
|
||||
SET @query_cache_size= @@global.query_cache_size;
|
||||
|
||||
--echo # Bug#28249 Query Cache returns wrong result with concurrent insert/ certain lock
|
||||
--echo # Establish connections user1,user2,user3 (user=root)
|
||||
connect (user1,localhost,root,,test,,);
|
||||
connect (user2,localhost,root,,test,,);
|
||||
connect (user3,localhost,root,,test,,);
|
||||
|
||||
--echo # Switch to connection user1
|
||||
connection user1;
|
||||
|
||||
SET GLOBAL query_cache_type=1;
|
||||
SET GLOBAL query_cache_limit=10000;
|
||||
SET GLOBAL query_cache_min_res_unit=0;
|
||||
SET GLOBAL query_cache_size= 100000;
|
||||
|
||||
FLUSH TABLES;
|
||||
--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);
|
||||
|
||||
--echo # Switch to connection user2
|
||||
connection user2;
|
||||
LOCK TABLE t2 WRITE;
|
||||
|
||||
--echo # Switch to connection user1
|
||||
connection user1;
|
||||
--echo # "send" the next select, "reap" the result later.
|
||||
--echo # The select will be blocked by the write lock on the t1.
|
||||
let $select_for_qc =
|
||||
SELECT *, (SELECT COUNT(*) FROM t2) FROM t1;
|
||||
send;
|
||||
eval $select_for_qc;
|
||||
|
||||
--echo # Switch to connection user3
|
||||
connection user3;
|
||||
# Typical information_schema.processlist content sufficient sleep time
|
||||
# ID USER COMMAND TIME STATE INFO
|
||||
# ....
|
||||
# 2 root Query 5 Locked SELECT *, (SELECT COUNT(*) FROM t2) FROM t1
|
||||
# ....
|
||||
# XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
# The values marked with 'X' must be reached.
|
||||
--echo # Poll till the select of connection user1 is blocked by the write lock on t1.
|
||||
let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = 'Locked'
|
||||
AND info = '$select_for_qc';
|
||||
--source include/wait_condition.inc
|
||||
eval
|
||||
SELECT user,command,state,info FROM information_schema.processlist
|
||||
WHERE state = 'Locked'
|
||||
AND info = '$select_for_qc';
|
||||
INSERT INTO t1 VALUES (4);
|
||||
|
||||
--echo # Switch to connection user2
|
||||
connection user2;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--echo # Switch to connection user1
|
||||
connection user1;
|
||||
#
|
||||
# Since the lock ordering rule in thr_multi_lock depends on
|
||||
# pointer values, from execution to execution we might have
|
||||
# different lock order, and therefore, sometimes lock t1 and block
|
||||
# on t2, and sometimes block on t2 right away. In the second case,
|
||||
# the following insert succeeds, and only then this select can
|
||||
# proceed, and we actually test nothing, as the very first select
|
||||
# returns 4 rows right away.
|
||||
# It's fine to have a test case that covers the problematic area
|
||||
# at least once in a while.
|
||||
--echo # Collecting ("reap") the result from the previously blocked select.
|
||||
--echo # The printing of the result (varies between 3 and 4 rows) set has to be suppressed.
|
||||
--disable_result_log
|
||||
--reap
|
||||
--enable_result_log
|
||||
|
||||
--echo # Switch to connection user3
|
||||
connection user3;
|
||||
--echo # The next select enforces that effects of "concurrent_inserts" like the
|
||||
--echo # record with a = 4 is missing in result sets can no more happen.
|
||||
SELECT 1 FROM t1 WHERE a = 4;
|
||||
|
||||
--echo # Switch to connection user1
|
||||
connection user1;
|
||||
--echo # The next result set must contain 4 rows.
|
||||
# If not, we have a regression of Bug#28249
|
||||
eval $select_for_qc;
|
||||
RESET QUERY CACHE;
|
||||
eval $select_for_qc;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo # Switch to connection default + close connections user1,user2,user3
|
||||
connection default;
|
||||
disconnect user1;
|
||||
disconnect user2;
|
||||
disconnect user3;
|
||||
|
||||
SET GLOBAL query_cache_type= @query_cache_type;
|
||||
SET GLOBAL query_cache_limit= @query_cache_limit;
|
||||
SET GLOBAL query_cache_min_res_unit= @query_cache_min_res_unit;
|
||||
SET GLOBAL query_cache_size= @query_cache_size;
|
||||
|
||||
|
Reference in New Issue
Block a user