125 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			125 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
|  | ### 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 | ||
|  | --source include/not_embedded.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 after 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; | ||
|  | 
 |