diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2017-04-28 19:42:32 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2017-05-04 15:25:30 +0200 |
commit | 8f8c379f1c85ebb5edca33eecaa6996340e2e241 (patch) | |
tree | 09f059a50bb5382e616f26fe31eae5435a9a7528 | |
parent | 96247be1a0dfa3035580b53b1c27a7247a410713 (diff) | |
download | mariadb-git-bb-10.2-MDEV-12485.tar.gz |
MDEV-12485 foreign key on delete cascade stale entries with query cache enabledbb-10.2-MDEV-12485
During merge of innodb code QC invalidation was removed from innodb part but not added to server part.
We decided to keep it in innodb to keep server/engine interface the same.
-rw-r--r-- | mysql-test/r/query_cache_innodb.result | 90 | ||||
-rw-r--r-- | mysql-test/t/query_cache_innodb.test | 84 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 34 |
3 files changed, 203 insertions, 5 deletions
diff --git a/mysql-test/r/query_cache_innodb.result b/mysql-test/r/query_cache_innodb.result new file mode 100644 index 00000000000..2f439948108 --- /dev/null +++ b/mysql-test/r/query_cache_innodb.result @@ -0,0 +1,90 @@ +# +# MDEV-12485: foreign key on delete cascade stale entries with +# query cache enabled +# +SET NAMES utf8; +set global query_cache_type=1; +set global query_cache_size=1024*1024; +set query_cache_type=1; +create table t1 ( id int unsigned auto_increment, primary key(id) ) engine=innodb; +create table t2 ( t2id int unsigned, id int unsigned, primary key(t2id, id), foreign key (`id`) references t1(`id`) on delete cascade ) engine=innodb; +insert into t1 values (1); +insert into t2 values (1,1); +select * from t2; +t2id id +1 1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +delete from t1; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +select * from t2; +t2id id +optimize table t2; +Table Op Msg_type Msg_text +test.t2 optimize note Table does not support optimize, doing recreate + analyze instead +test.t2 optimize status OK +select * from t2; +t2id id +drop table t2; +drop table t1; +create database `testdatabase$Ї`; +use `testdatabase$Ї`; +create table `t1$Ї` ( id int unsigned auto_increment, primary key(id) ) engine=innodb; +create table `t2$Ї` ( t2id int unsigned, id int unsigned, primary key(t2id, id), foreign key (`id`) references `t1$Ї`(`id`) on delete cascade ) engine=innodb; +insert into `t1$Ї` values (1); +insert into `t2$Ї`values (1,1); +select * from `t2$Ї`; +t2id id +1 1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +delete from `t1$Ї`; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +select * from `t2$Ї`; +t2id id +optimize table `t2$Ї`; +Table Op Msg_type Msg_text +testdatabase$Ї.t2$Ї optimize note Table does not support optimize, doing recreate + analyze instead +testdatabase$Ї.t2$Ї optimize status OK +select * from `t2$Ї`; +t2id id +use test; +drop database `testdatabase$Ї`; +SET NAMES default; +create database `#mysql50#-`; +use `#mysql50#-`; +create table `#mysql50#t-1` ( id int unsigned auto_increment, primary key(id) ) engine=innodb; +create table `#mysql50#t-2` ( t2id int unsigned, id int unsigned, primary key(t2id, id), foreign key (`id`) references `#mysql50#t-1`(`id`) on delete cascade ) engine=innodb; +insert into `#mysql50#t-1` values (1); +insert into `#mysql50#t-2`values (1,1); +select * from `#mysql50#t-2`; +t2id id +1 1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +delete from `#mysql50#t-1`; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +select * from `#mysql50#t-2`; +t2id id +optimize table `#mysql50#t-2`; +Table Op Msg_type Msg_text +#mysql50#-.#mysql50#t-2 optimize note Table does not support optimize, doing recreate + analyze instead +#mysql50#-.#mysql50#t-2 optimize status OK +select * from `#mysql50#t-2`; +t2id id +use test; +drop database `#mysql50#-`; +SET NAMES default; +FOUND 12 /\[ERROR\] Invalid \(old\?\) table or database name/ in mysqld.1.err +set global query_cache_type=DEFAULT; +set global query_cache_size=DEFAULT; +End of 10.2 tests diff --git a/mysql-test/t/query_cache_innodb.test b/mysql-test/t/query_cache_innodb.test new file mode 100644 index 00000000000..588cdf31c5a --- /dev/null +++ b/mysql-test/t/query_cache_innodb.test @@ -0,0 +1,84 @@ +--source include/have_innodb.inc +--source include/have_query_cache.inc + +--echo # +--echo # MDEV-12485: foreign key on delete cascade stale entries with +--echo # query cache enabled +--echo # + +SET NAMES utf8; +set global query_cache_type=1; +set global query_cache_size=1024*1024; +set query_cache_type=1; + +create table t1 ( id int unsigned auto_increment, primary key(id) ) engine=innodb; + +create table t2 ( t2id int unsigned, id int unsigned, primary key(t2id, id), foreign key (`id`) references t1(`id`) on delete cascade ) engine=innodb; + +insert into t1 values (1); +insert into t2 values (1,1); +select * from t2; +show status like "Qcache_queries_in_cache"; + +delete from t1; +show status like "Qcache_queries_in_cache"; +select * from t2; + +optimize table t2; +select * from t2; +drop table t2; +drop table t1; + +create database `testdatabase$Ї`; +use `testdatabase$Ї`; +create table `t1$Ї` ( id int unsigned auto_increment, primary key(id) ) engine=innodb; + +create table `t2$Ї` ( t2id int unsigned, id int unsigned, primary key(t2id, id), foreign key (`id`) references `t1$Ї`(`id`) on delete cascade ) engine=innodb; + +insert into `t1$Ї` values (1); +insert into `t2$Ї`values (1,1); +select * from `t2$Ї`; +show status like "Qcache_queries_in_cache"; + +delete from `t1$Ї`; +show status like "Qcache_queries_in_cache"; +select * from `t2$Ї`; + +optimize table `t2$Ї`; +select * from `t2$Ї`; + +use test; +drop database `testdatabase$Ї`; +SET NAMES default; + +create database `#mysql50#-`; +use `#mysql50#-`; +create table `#mysql50#t-1` ( id int unsigned auto_increment, primary key(id) ) engine=innodb; + +create table `#mysql50#t-2` ( t2id int unsigned, id int unsigned, primary key(t2id, id), foreign key (`id`) references `#mysql50#t-1`(`id`) on delete cascade ) engine=innodb; + +insert into `#mysql50#t-1` values (1); +insert into `#mysql50#t-2`values (1,1); +select * from `#mysql50#t-2`; +show status like "Qcache_queries_in_cache"; + +delete from `#mysql50#t-1`; +show status like "Qcache_queries_in_cache"; +select * from `#mysql50#t-2`; + +optimize table `#mysql50#t-2`; +select * from `#mysql50#t-2`; + +use test; +drop database `#mysql50#-`; +SET NAMES default; +--disable_query_log +call mtr.add_suppression("\\[ERROR\\] Invalid \\(old\\?\\) table or database name 't?-[12]?\\'"); +--enable_query_log +--let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN=\\[ERROR\\] Invalid \\(old\\?\\) table or database name +--source include/search_pattern_in_file.inc + +set global query_cache_type=DEFAULT; +set global query_cache_size=DEFAULT; +--echo End of 10.2 tests diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c486b0d4c4d..356dd36b43c 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3441,11 +3441,35 @@ innobase_invalidate_query_cache( above the InnoDB trx_sys_t->lock. The caller of this function must not have latches of a lower rank. */ - /* Argument TRUE below means we are using transactions */ - mysql_query_cache_invalidate4(trx->mysql_thd, - full_name, - (uint32) full_name_len, - TRUE); +#ifdef HAVE_QUERY_CACHE + char qcache_key_name[2 * (NAME_LEN + 1)]; + char db_name[NAME_CHAR_LEN * MY_CS_MBMAXLEN + 1]; + const char *key_ptr; + size_t tabname_len; + size_t dbname_len; + + // Extract the database name. + key_ptr= strchr(full_name, '/'); + DBUG_ASSERT(key_ptr != NULL); // Database name should be present + memcpy(db_name, full_name, (dbname_len= (key_ptr - full_name))); + db_name[dbname_len]= '\0'; + + /* Construct the key("db-name\0table$name\0") for the query cache using + the path name("db@002dname\0table@0024name\0") of the table in its + canonical form. */ + dbname_len = filename_to_tablename(db_name, qcache_key_name, + sizeof(qcache_key_name)); + tabname_len = filename_to_tablename(++key_ptr, + (qcache_key_name + dbname_len + 1), + sizeof(qcache_key_name) - + dbname_len - 1); + + /* Argument TRUE below means we are using transactions */ + mysql_query_cache_invalidate4(trx->mysql_thd, + qcache_key_name, + (dbname_len + tabname_len + 2), + TRUE); +#endif } /** Quote a standard SQL identifier like index or column name. |