182 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| flush status;
 | |
| set query_cache_type=DEMAND;
 | |
| set global query_cache_size= 1024*768;
 | |
| drop table if exists t1;
 | |
| create table t1 (a varchar(100));
 | |
| insert into t1 values ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
 | |
| Activate debug hook and attempt to retrieve the statement from the cache.
 | |
| set session debug='+d,wait_in_query_cache_insert';
 | |
| select SQL_CACHE * from t1;;
 | |
| On a second connection; clear the query cache.
 | |
| show status like 'Qcache_queries_in_cache';
 | |
| Variable_name	Value
 | |
| Qcache_queries_in_cache	1
 | |
| set global query_cache_size= 0;
 | |
| 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;
 | |
| Show query cache status.
 | |
| show status like 'Qcache_queries_in_cache';
 | |
| Variable_name	Value
 | |
| Qcache_queries_in_cache	0
 | |
| set global query_cache_size= 0;
 | |
| use test;
 | |
| drop table t1;
 | |
| SET @old_concurrent_insert= @@GLOBAL.concurrent_insert;
 | |
| SET @old_query_cache_size= @@GLOBAL.query_cache_size;
 | |
| DROP TABLE IF EXISTS t1, t2;
 | |
| 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;
 | |
| # Switch to connection con1
 | |
| SET SESSION debug='+d,wait_after_query_cache_invalidate';
 | |
| # Send concurrent insert, will wait in the query cache table invalidate
 | |
| INSERT INTO t1 VALUES (4);
 | |
| # Switch to connection default
 | |
| # Wait for concurrent insert to reach the debug point
 | |
| # Switch to connection con2
 | |
| # Send SELECT that shouldn't be cached
 | |
| SELECT * FROM t1;
 | |
| a
 | |
| 1
 | |
| 2
 | |
| 3
 | |
| # Switch to connection default
 | |
| # 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;
 | |
| # Switch to connection con1
 | |
| # Gather insert result
 | |
| SHOW STATUS LIKE "Qcache_queries_in_cache";
 | |
| Variable_name	Value
 | |
| Qcache_queries_in_cache	0
 | |
| # Test that it's cacheable
 | |
| SELECT * FROM t1;
 | |
| a
 | |
| 1
 | |
| 2
 | |
| 3
 | |
| 4
 | |
| SHOW STATUS LIKE "Qcache_queries_in_cache";
 | |
| Variable_name	Value
 | |
| Qcache_queries_in_cache	1
 | |
| # Disconnect
 | |
| # 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;
 | |
| #
 | |
| # Bug43758 Query cache can lock up threads in 'freeing items' state
 | |
| #
 | |
| FLUSH STATUS;
 | |
| SET GLOBAL query_cache_type=DEMAND;
 | |
| SET GLOBAL query_cache_size= 1024*768;
 | |
| DROP TABLE IF EXISTS t1,t2,t3,t4,t5;
 | |
| CREATE TABLE t1 (a VARCHAR(100));
 | |
| CREATE TABLE t2 (a VARCHAR(100));
 | |
| CREATE TABLE t3 (a VARCHAR(100));
 | |
| CREATE TABLE t4 (a VARCHAR(100));
 | |
| CREATE TABLE t5 (a VARCHAR(100));
 | |
| INSERT INTO t1 VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
 | |
| INSERT INTO t2 VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
 | |
| INSERT INTO t3 VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
 | |
| INSERT INTO t4 VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
 | |
| INSERT INTO t5 VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
 | |
| =================================== Connection thd1
 | |
| **
 | |
| ** Load Query Cache with a result set and one table.
 | |
| **
 | |
| SELECT SQL_CACHE * FROM t1;
 | |
| a
 | |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 | |
| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
 | |
| *************************************************************************
 | |
| ** We want to accomplish the following state:
 | |
| **  - Query cache status: TABLE_FLUSH_IN_PROGRESS
 | |
| **  - THD1: invalidate_table_internal (iterating query blocks)
 | |
| **  - THD2: query_cache_insert (cond_wait)
 | |
| **  - THD3: query_cache_insert (cond_wait)
 | |
| **  - No thread should be holding the structure_guard_mutex.
 | |
| **
 | |
| ** First step is to place a DELETE-statement on the debug hook just
 | |
| ** before the mutex lock in invalidate_table_internal.
 | |
| ** This will allow new result sets to be written into the QC.
 | |
| ** 
 | |
| SET SESSION debug='+d,wait_in_query_cache_invalidate1';
 | |
| SET SESSION debug='+d,wait_in_query_cache_invalidate2';
 | |
| DELETE FROM t1 WHERE a like '%a%';;
 | |
| =================================== Connection default
 | |
| ** Assert that the expect process status is obtained.
 | |
| **
 | |
| =================================== Connection thd2
 | |
| ** On THD2: Insert a result into the cache. This attempt will be blocked
 | |
| ** because of a debug hook placed just before the mutex lock after which
 | |
| ** the first part of the result set is written.
 | |
| SET SESSION debug='+d,wait_in_query_cache_insert';
 | |
| SELECT SQL_CACHE * FROM t2 UNION SELECT * FROM t3;
 | |
| =================================== Connection thd3
 | |
| ** On THD3: Insert another result into the cache and block on the same
 | |
| ** debug hook.
 | |
| SET SESSION debug='+d,wait_in_query_cache_insert';
 | |
| SELECT SQL_CACHE * FROM t4 UNION SELECT * FROM t5;;
 | |
| =================================== Connection default
 | |
| ** Assert that the two SELECT-stmt threads to reach the hook.
 | |
| **
 | |
| **
 | |
| ** Signal the DELETE thread, THD1, to continue. It will enter the mutex
 | |
| ** lock and set query cache status to TABLE_FLUSH_IN_PROGRESS and then
 | |
| ** unlock the mutex before stopping on the next debug hook.
 | |
| SELECT SQL_NO_CACHE id FROM information_schema.processlist WHERE state='wait_in_query_cache_invalidate1' LIMIT 1 INTO @flush_thread_id;
 | |
| KILL QUERY @flush_thread_id;
 | |
| ** Assert that we reach the next debug hook.
 | |
| **
 | |
| ** Signal the remaining debug hooks blocking THD2 and THD3.
 | |
| ** The threads will grab the guard mutex enter the wait condition and
 | |
| ** and finally release the mutex. The threads will continue to wait
 | |
| ** until a broadcast signal reaches them causing both threads to 
 | |
| ** come alive and check the condition.
 | |
| SELECT SQL_NO_CACHE id FROM information_schema.processlist WHERE state='wait_in_query_cache_insert' ORDER BY id ASC LIMIT 1 INTO @thread_id;
 | |
| KILL QUERY @thread_id;
 | |
| SELECT SQL_NO_CACHE id FROM information_schema.processlist WHERE state='wait_in_query_cache_insert' ORDER BY id DESC LIMIT 1 INTO @thread_id;
 | |
| KILL QUERY @thread_id;
 | |
| **
 | |
| ** Finally signal the DELETE statement on THD1 one last time.
 | |
| ** The stmt will complete the query cache invalidation and return 
 | |
| ** cache status to NO_FLUSH_IN_PROGRESS. On the status change
 | |
| ** One signal will be sent to the thread group waiting for executing
 | |
| ** invalidations and a broadcast signal will be sent to the thread 
 | |
| ** group holding result set writers.
 | |
| SELECT SQL_NO_CACHE id FROM information_schema.processlist WHERE state='wait_in_query_cache_invalidate2' LIMIT 1 INTO @flush_thread_id;
 | |
| KILL QUERY @flush_thread_id;
 | |
| **
 | |
| *************************************************************************
 | |
| ** No tables should be locked
 | |
| =================================== Connection thd2
 | |
| a
 | |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 | |
| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
 | |
| DELETE FROM t1;
 | |
| DELETE FROM t2;
 | |
| DELETE FROM t3;
 | |
| =================================== Connection thd3
 | |
| a
 | |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 | |
| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
 | |
| DELETE FROM t4;
 | |
| DELETE FROM t5;
 | |
| =================================== Connection thd1
 | |
| ** Done.
 | |
| SET GLOBAL query_cache_size= 0;
 | |
| # Restore defaults
 | |
| RESET QUERY CACHE;
 | |
| FLUSH STATUS;
 | |
| DROP TABLE t1,t2,t3,t4,t5;
 | |
| SET GLOBAL query_cache_size= DEFAULT;
 | |
| SET GLOBAL query_cache_type= DEFAULT;
 |