From b86dc86ee9841cb35d363992579299355f9245c9 Mon Sep 17 00:00:00 2001 From: Serge Kozlov Date: Thu, 19 Feb 2009 23:29:12 +0300 Subject: [PATCH 1/2] Bug#41423. 1. Constant values of binlog positions replaced by seeking them in binlog/relay log. 2. Updated result file --- mysql-test/suite/rpl/r/rpl_row_until.result | 77 +++++----- mysql-test/suite/rpl/t/rpl_row_until.test | 147 +++++++++++++------- 2 files changed, 132 insertions(+), 92 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_row_until.result b/mysql-test/suite/rpl/r/rpl_row_until.result index be1ec51f74a..ad54450af74 100644 --- a/mysql-test/suite/rpl/r/rpl_row_until.result +++ b/mysql-test/suite/rpl/r/rpl_row_until.result @@ -4,16 +4,17 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CREATE TABLE t1(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3),(4); +DROP TABLE t1; +CREATE TABLE t2(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t2 VALUES (1),(2); +INSERT INTO t2 VALUES (3),(4); +DROP TABLE t2; include/stop_slave.inc -create table t1(n int not null auto_increment primary key); -insert into t1 values (1),(2),(3),(4); -drop table t1; -create table t2(n int not null auto_increment primary key); -insert into t2 values (1),(2); -insert into t2 values (3),(4); -drop table t2; -start slave until master_log_file='master-bin.000001', master_log_pos=311; -select * from t1; +RESET SLAVE; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=master_pos_drop_t1 +SELECT * FROM t1; n 1 2 @@ -23,10 +24,10 @@ SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port MASTER_PORT +Master_Port # Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1161 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -41,11 +42,11 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 454 +Exec_Master_Log_Pos MASTER_POS_DROP_T1 Relay_Log_Space # Until_Condition Master Until_Log_File master-bin.000001 -Until_Log_Pos 311 +Until_Log_Pos MASTER_POS_DROP_T1 Master_SSL_Allowed No Master_SSL_CA_File Master_SSL_CA_Path @@ -58,8 +59,8 @@ Last_IO_Errno # Last_IO_Error # Last_SQL_Errno 0 Last_SQL_Error -start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; -select * from t1; +START SLAVE UNTIL MASTER_LOG_FILE='master-no-such-bin.000001', MASTER_LOG_POS=291; +SELECT * FROM t1; n 1 2 @@ -69,10 +70,10 @@ SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port MASTER_PORT +Master_Port # Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1161 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -87,7 +88,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 454 +Exec_Master_Log_Pos MASTER_POS_DROP_T1 Relay_Log_Space # Until_Condition Master Until_Log_File master-no-such-bin.000001 @@ -104,8 +105,8 @@ Last_IO_Errno # Last_IO_Error # Last_SQL_Errno 0 Last_SQL_Error -start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=1014; -select * from t2; +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', RELAY_LOG_POS=relay_pos_insert1_t2 +SELECT * FROM t2; n 1 2 @@ -113,10 +114,10 @@ SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port MASTER_PORT +Master_Port # Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1161 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -131,11 +132,11 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 868 +Exec_Master_Log_Pos MASTER_POS_INSERT1_T2 Relay_Log_Space # Until_Condition Relay -Until_Log_File slave-relay-bin.000004 -Until_Log_Pos 1014 +Until_Log_File slave-relay-bin.000002 +Until_Log_Pos RELAY_POS_INSERT1_T2 Master_SSL_Allowed No Master_SSL_CA_File Master_SSL_CA_Path @@ -148,17 +149,17 @@ Last_IO_Errno # Last_IO_Error # Last_SQL_Errno 0 Last_SQL_Error -start slave; +START SLAVE; include/stop_slave.inc -start slave sql_thread until master_log_file='master-bin.000001', master_log_pos=740; +START SLAVE SQL_THREAD UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=master_pos_create_t2 SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port MASTER_PORT +Master_Port # Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1161 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -173,11 +174,11 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 1161 +Exec_Master_Log_Pos MASTER_POS_DROP_T2 Relay_Log_Space # Until_Condition Master Until_Log_File master-bin.000001 -Until_Log_Pos 740 +Until_Log_Pos MASTER_POS_CREATE_T2 Master_SSL_Allowed No Master_SSL_CA_File Master_SSL_CA_Path @@ -190,17 +191,17 @@ Last_IO_Errno # Last_IO_Error # Last_SQL_Errno 0 Last_SQL_Error -start slave until master_log_file='master-bin', master_log_pos=561; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin', MASTER_LOG_POS=561; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL -start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=561, RELAY_LOG_POS=12; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL -start slave until master_log_file='master-bin.000001'; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001'; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL -start slave until relay_log_file='slave-relay-bin.000002'; +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000009'; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL -start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561; +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', MASTER_LOG_POS=561; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL -start slave; -start slave until master_log_file='master-bin.000001', master_log_pos=740; +START SLAVE; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=740; Warnings: Note 1254 Slave is already running diff --git a/mysql-test/suite/rpl/t/rpl_row_until.test b/mysql-test/suite/rpl/t/rpl_row_until.test index d89de7d9ebd..fe859218ed3 100644 --- a/mysql-test/suite/rpl/t/rpl_row_until.test +++ b/mysql-test/suite/rpl/t/rpl_row_until.test @@ -2,76 +2,115 @@ -- source include/have_binlog_format_row.inc -- source include/master-slave.inc -# Test is dependent on binlog positions +# Note: The test is dependent on binlog positions # prepare version for substitutions let $VERSION=`select version()`; -# stop slave before he will start replication also sync with master -# for avoiding undetermenistic behaviour +# Create some events on master +connection master; +CREATE TABLE t1(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3),(4); +DROP TABLE t1; +# Save master log postion for query DROP TABLE t1 +save_master_pos; +let $master_pos_drop_t1= query_get_value(SHOW BINLOG EVENTS, Pos, 7); + +CREATE TABLE t2(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +# Save master log postion for query CREATE TABLE t2 +save_master_pos; +let $master_pos_create_t2= query_get_value(SHOW BINLOG EVENTS, Pos, 8); + +INSERT INTO t2 VALUES (1),(2); +save_master_pos; +# Save master log postion for query INSERT INTO t2 VALUES (1),(2); +let $master_pos_insert1_t2= query_get_value(SHOW BINLOG EVENTS, End_log_pos, 12); +sync_slave_with_master; + +# Save relay log postion for query INSERT INTO t2 VALUES (1),(2); +let $relay_pos_insert1_t2= query_get_value(show slave status, Relay_Log_Pos, 1); + +connection master; +INSERT INTO t2 VALUES (3),(4); +DROP TABLE t2; +# Save master log postion for query INSERT INTO t2 VALUES (1),(2); +let $master_pos_drop_t2= query_get_value(SHOW BINLOG EVENTS, End_log_pos, 17); +sync_slave_with_master; + +--source include/stop_slave.inc +# Reset slave. +RESET SLAVE; +--disable_query_log +eval CHANGE MASTER TO MASTER_USER='root', MASTER_CONNECT_RETRY=1, MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT; +--enable_query_log + +# Try to replicate all queries until drop of t1 +connection slave; +echo START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=master_pos_drop_t1; +--disable_query_log +eval START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=$master_pos_drop_t1; +--enable_query_log +--source include/wait_for_slave_sql_to_stop.inc + +# Here table should be still not deleted +SELECT * FROM t1; +--replace_result $master_pos_drop_t1 MASTER_POS_DROP_T1 +--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 23 # 33 # 35 # 36 # +query_vertical SHOW SLAVE STATUS; + +# This should fail right after start +START SLAVE UNTIL MASTER_LOG_FILE='master-no-such-bin.000001', MASTER_LOG_POS=291; +--source include/wait_for_slave_sql_to_stop.inc +# again this table should be still not deleted +SELECT * FROM t1; +--replace_result $master_pos_drop_t1 MASTER_POS_DROP_T1 +--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 23 # 33 # 35 # 36 # +query_vertical SHOW SLAVE STATUS; + +# Try replicate all up to and not including the second insert to t2; +echo START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', RELAY_LOG_POS=relay_pos_insert1_t2; +--disable_query_log +eval START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', RELAY_LOG_POS=$relay_pos_insert1_t2; +--enable_query_log +--source include/wait_for_slave_sql_to_stop.inc +SELECT * FROM t2; +--replace_result $relay_pos_insert1_t2 RELAY_POS_INSERT1_T2 $master_pos_insert1_t2 MASTER_POS_INSERT1_T2 +--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 23 # 33 # 35 # 36 # +query_vertical SHOW SLAVE STATUS; + +# clean up +START SLAVE; +--source include/wait_for_slave_to_start.inc +connection master; sync_slave_with_master; --source include/stop_slave.inc -connection master; -# create some events on master -create table t1(n int not null auto_increment primary key); -insert into t1 values (1),(2),(3),(4); -drop table t1; -create table t2(n int not null auto_increment primary key); -insert into t2 values (1),(2); -insert into t2 values (3),(4); -drop table t2; - -# try to replicate all queries until drop of t1 -connection slave; -start slave until master_log_file='master-bin.000001', master_log_pos=311; ---source include/wait_for_slave_sql_to_stop.inc -# here table should be still not deleted -select * from t1; -source include/show_slave_status.inc; - -# this should fail right after start -start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; ---source include/wait_for_slave_sql_to_stop.inc -# again this table should be still not deleted -select * from t1; -source include/show_slave_status.inc; - -# try replicate all up to and not including the second insert to t2; -start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=1014; ---source include/wait_for_slave_sql_to_stop.inc -select * from t2; -source include/show_slave_status.inc; - -# clean up -start slave; -connection master; -save_master_pos; -connection slave; -sync_with_master; ---source include/stop_slave.inc - -# this should stop immediately as we are already there -start slave sql_thread until master_log_file='master-bin.000001', master_log_pos=740; ---let $slave_param= Until_Log_Pos ---let $slave_param_value= 740 +# This should stop immediately as we are already there +echo START SLAVE SQL_THREAD UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=master_pos_create_t2; +--disable_query_log +eval START SLAVE SQL_THREAD UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=$master_pos_create_t2; +--enable_query_log +let $slave_param= Until_Log_Pos; +let $slave_param_value= $master_pos_create_t2; --source include/wait_for_slave_param.inc --source include/wait_for_slave_sql_to_stop.inc # here the sql slave thread should be stopped --replace_result bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004 -source include/show_slave_status.inc; +--replace_result $master_pos_create_t2 MASTER_POS_CREATE_T2 $master_pos_drop_t2 MASTER_POS_DROP_T2 +--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 23 # 33 # 35 # 36 # +query_vertical SHOW SLAVE STATUS; #testing various error conditions --error 1277 -start slave until master_log_file='master-bin', master_log_pos=561; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin', MASTER_LOG_POS=561; --error 1277 -start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=561, RELAY_LOG_POS=12; --error 1277 -start slave until master_log_file='master-bin.000001'; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001'; --error 1277 -start slave until relay_log_file='slave-relay-bin.000002'; +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000009'; --error 1277 -start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561; +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', MASTER_LOG_POS=561; # Warning should be given for second command -start slave; -start slave until master_log_file='master-bin.000001', master_log_pos=740; +START SLAVE; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=740; From 664bb23a30572e89da319c9d2f201a7de3828c1b Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 19 Feb 2009 18:09:35 -0300 Subject: [PATCH 2/2] Bug#41098: Query Cache returns wrong result with concurrent insert The problem is that select queries executed concurrently with a concurrent insert on a MyISAM table could be cached if the select started after the query cache invalidation but before the unlock of tables performed by the concurrent insert. This race could happen because the concurrent insert was failing to prevent cache of select queries happening at the same time. The solution is to add a 'uncacheable' status flag to signal that a concurrent insert is being performed on the table and that queries executing at the same time shouldn't cache the results. mysql-test/r/query_cache_debug.result: Add test case result for Bug#41098 mysql-test/t/disabled.def: Re-enable test case. mysql-test/t/query_cache_debug.test: Add test case for Bug#41098 sql/sql_cache.cc: Debug sync point for regression testing purposes. sql/sql_insert.cc: Remove meaningless query cache invalidate. There is already a preceding invalidate for queries that started before the concurrent insert. storage/myisam/ha_myisam.cc: Check for a active concurrent insert. storage/myisam/mi_locking.c: Signal the start of a concurrent insert. Flag is zeroed once the state is updated back. storage/myisam/myisamdef.h: Add flag to signal a active concurrent insert. --- mysql-test/r/query_cache_debug.result | 49 +++++++++++++++++++ mysql-test/t/disabled.def | 1 - mysql-test/t/query_cache_debug.test | 68 +++++++++++++++++++++++++++ sql/sql_cache.cc | 3 ++ sql/sql_insert.cc | 14 ------ storage/myisam/ha_myisam.cc | 9 ++++ storage/myisam/mi_locking.c | 2 + storage/myisam/myisamdef.h | 1 + 8 files changed, 132 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/query_cache_debug.result b/mysql-test/r/query_cache_debug.result index c90165368e3..b03a71d3fec 100644 --- a/mysql-test/r/query_cache_debug.result +++ b/mysql-test/r/query_cache_debug.result @@ -22,3 +22,52 @@ 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; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index f61090102ff..3f61176e37b 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,5 +10,4 @@ # ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. -query_cache_28249 : Bug#41098 Query Cache returns wrong result with concurrent insert innodb_bug39438 : BUG#42383 2009-01-28 lsoares "This fails in embedded and on windows. Note that this test is not run on windows and on embedded in PB for main trees currently" diff --git a/mysql-test/t/query_cache_debug.test b/mysql-test/t/query_cache_debug.test index 18dfe487ac3..8cf5e9d4b16 100644 --- a/mysql-test/t/query_cache_debug.test +++ b/mysql-test/t/query_cache_debug.test @@ -44,3 +44,71 @@ set global query_cache_size= 0; use test; drop table t1; +# +# Bug#41098: Query Cache returns wrong result with concurrent insert +# + +SET @old_concurrent_insert= @@GLOBAL.concurrent_insert; +SET @old_query_cache_size= @@GLOBAL.query_cache_size; + +--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); + +SET GLOBAL concurrent_insert= 1; +SET GLOBAL query_cache_size= 1024*512; +SET GLOBAL query_cache_type= ON; + +connect(con1,localhost,root,,test,,); +connect(con2,localhost,root,,test,,); + +connection con1; +--echo # Switch to connection con1 +SET SESSION debug='+d,wait_after_query_cache_invalidate'; +--echo # Send concurrent insert, will wait in the query cache table invalidate +--send INSERT INTO t1 VALUES (4) + +connection default; +--echo # Switch to connection default +--echo # Wait for concurrent insert to reach the debug point +let $wait_condition= + SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE STATE = "wait_after_query_cache_invalidate" AND + INFO = "INSERT INTO t1 VALUES (4)"; +--source include/wait_condition.inc + +connection con2; +--echo # Switch to connection con2 +--echo # Send SELECT that shouldn't be cached +SELECT * FROM t1; + +connection default; +--echo # Switch to connection default +--echo # 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; + +connection con1; +--echo # Switch to connection con1 +--echo # Gather insert result +--reap +SHOW STATUS LIKE "Qcache_queries_in_cache"; +--echo # Test that it's cacheable +SELECT * FROM t1; +SHOW STATUS LIKE "Qcache_queries_in_cache"; + +--echo # Disconnect +disconnect con1; +disconnect con2; + +connection default; +--echo # 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; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 7c97ee4cf32..4a5b75c4f78 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1518,6 +1518,9 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used, invalidate_table(thd, tables_used); } + DBUG_EXECUTE_IF("wait_after_query_cache_invalidate", + debug_wait_for_kill("wait_after_query_cache_invalidate");); + DBUG_VOID_RETURN; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index fcf86edeaa9..e712727a78b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -904,20 +904,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, } DBUG_ASSERT(transactional_table || !changed || thd->transaction.stmt.modified_non_trans_table); - - if (thd->lock) - { - /* - Invalidate the table in the query cache if something changed - after unlocking when changes become fisible. - TODO: this is workaround. right way will be move invalidating in - the unlock procedure. - */ - if (lock_type == TL_WRITE_CONCURRENT_INSERT && changed) - { - query_cache_invalidate3(thd, table_list, 1); - } - } } thd_proc_info(thd, "end"); /* diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 4073044bf63..ad06ea4b7f0 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -2152,6 +2152,15 @@ my_bool ha_myisam::register_query_cache_table(THD *thd, char *table_name, } } + /* + This query execution might have started after the query cache was flushed + by a concurrent INSERT. In this case, don't cache this statement as the + data file length difference might not be visible yet if the tables haven't + been unlocked by the concurrent insert thread. + */ + if (file->state->uncacheable) + DBUG_RETURN(FALSE); + /* It is ok to try to cache current statement. */ DBUG_RETURN(TRUE); } diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index ec359d13a14..6a4c21160f4 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -293,6 +293,8 @@ void mi_get_status(void* param, int concurrent_insert) info->save_state=info->s->state.state; info->state= &info->save_state; info->append_insert_at_end= concurrent_insert; + if (concurrent_insert) + info->s->state.state.uncacheable= TRUE; DBUG_VOID_RETURN; } diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 9af3f652c5f..b64c7f6bd7f 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -38,6 +38,7 @@ typedef struct st_mi_status_info my_off_t key_file_length; my_off_t data_file_length; ha_checksum checksum; + my_bool uncacheable; /* Active concurrent insert */ } MI_STATUS_INFO; typedef struct st_mi_state_info