1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
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;
|