### 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 --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;