diff options
-rw-r--r-- | innobase/include/srv0srv.h | 1 | ||||
-rw-r--r-- | innobase/srv/srv0srv.c | 2 | ||||
-rw-r--r-- | innobase/trx/trx0purge.c | 24 | ||||
-rw-r--r-- | mysql-test/r/query_cache.result | 13 | ||||
-rw-r--r-- | mysql-test/t/query_cache.test | 11 | ||||
-rw-r--r-- | sql/ha_innodb.h | 1 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/set_var.cc | 4 | ||||
-rw-r--r-- | sql/sql_base.cc | 5 | ||||
-rw-r--r-- | sql/sql_cache.cc | 31 | ||||
-rw-r--r-- | sql/sql_cache.h | 6 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 |
12 files changed, 94 insertions, 7 deletions
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index ecd57bae47c..6cfe9cef927 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -111,6 +111,7 @@ extern ibool srv_use_doublewrite_buf; extern ibool srv_set_thread_priorities; extern int srv_query_thread_priority; +extern ulint srv_max_purge_lag; extern ibool srv_use_awe; extern ibool srv_use_adaptive_hash_indexes; diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index b8d03cfab5f..582f43fa4ec 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -881,6 +881,8 @@ srv_general_init(void) /*======================= InnoDB Server FIFO queue =======================*/ +/* Maximum allowable purge history length. <=0 means 'infinite'. */ +ulint srv_max_purge_lag = 0; /************************************************************************* Puts an OS thread to wait if there are too many concurrent threads diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c index 5c62640e011..6726d7ca609 100644 --- a/innobase/trx/trx0purge.c +++ b/innobase/trx/trx0purge.c @@ -1069,6 +1069,30 @@ trx_purge(void) } } + /* Determine how much data manipulation language (DML) statements + need to be delayed in order to reduce the lagging of the purge + thread. */ + srv_dml_needed_delay = 0; /* in microseconds; default: no delay */ + + /* If we cannot advance the 'purge view' because of an old + 'consistent read view', then the DML statements cannot be delayed. + Also, srv_max_purge_lag <= 0 means 'infinity'. */ + if (srv_max_purge_lag > 0 + && !UT_LIST_GET_LAST(trx_sys->view_list)) { + float ratio = (float) trx_sys->rseg_history_len + / srv_max_purge_lag; + if (ratio > ULINT_MAX / 10000) { + /* Avoid overflow: maximum delay is 4295 seconds */ + srv_dml_needed_delay = ULINT_MAX; + } else if (ratio > 1) { + /* If the history list length exceeds the + innodb_max_purge_lag, the + data manipulation statements are delayed + by at least 5000 microseconds. */ + srv_dml_needed_delay = (ulint) ((ratio - .5) * 10000); + } + } + purge_sys->view = read_view_oldest_copy_or_open_new(NULL, purge_sys->heap); mutex_exit(&kernel_mutex); diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index d68da39b19f..9f61b029391 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -791,6 +791,19 @@ Qcache_queries_in_cache 1 unlock table; drop table t1,t2; set query_cache_wlock_invalidate=default; +CREATE TABLE t1 (id INT PRIMARY KEY); +insert into t1 values (1),(2),(3); +select * from t1; +id +1 +2 +3 +create temporary table t1 (a int not null auto_increment +primary key); +select * from t1; +a +drop table t1; +drop table t1; SET NAMES koi8r; CREATE TABLE t1 (a char(1) character set koi8r); INSERT INTO t1 VALUES (_koi8r'á'),(_koi8r'Á'); diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 66e9f31823a..d570073b1d2 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -561,6 +561,17 @@ unlock table; drop table t1,t2; set query_cache_wlock_invalidate=default; +# +# hiding real table stored in query cache by temporary table +# +CREATE TABLE t1 (id INT PRIMARY KEY); +insert into t1 values (1),(2),(3); +select * from t1; +create temporary table t1 (a int not null auto_increment +primary key); +select * from t1; +drop table t1; +drop table t1; # # Test character set related variables: diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 7f7b000a100..c10beacac1b 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -198,6 +198,7 @@ extern my_bool innobase_very_fast_shutdown; /* set this to 1 just before is equivalent to a 'crash' */ extern "C" { extern ulong srv_max_buf_pool_modified_pct; +extern ulong srv_max_purge_lag; extern ulong srv_auto_extend_increment; extern ulong srv_max_purge_lag; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 18944aebad9..770b7057661 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -681,6 +681,7 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags); #define MYSQL_HA_FLUSH_ALL 0x02 /* sql_base.cc */ +#define TMP_TABLE_KEY_EXTRA 8 void set_item_name(Item *item,char *pos,uint length); bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type, char *length, char *decimal, diff --git a/sql/set_var.cc b/sql/set_var.cc index 66ed273d531..d8c1ed2c975 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -352,6 +352,8 @@ sys_var_thd_ulong sys_net_wait_timeout("wait_timeout", #ifdef HAVE_INNOBASE_DB sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct", &srv_max_buf_pool_modified_pct); +sys_var_long_ptr sys_innodb_max_purge_lag("innodb_max_purge_lag", + &srv_max_purge_lag); sys_var_thd_bool sys_innodb_table_locks("innodb_table_locks", &SV::innodb_table_locks); sys_var_long_ptr sys_innodb_autoextend_increment("innodb_autoextend_increment", @@ -608,6 +610,7 @@ sys_var *sys_variables[]= &sys_os, #ifdef HAVE_INNOBASE_DB &sys_innodb_max_dirty_pages_pct, + &sys_innodb_max_purge_lag, &sys_innodb_table_locks, &sys_innodb_max_purge_lag, &sys_innodb_autoextend_increment, @@ -704,6 +707,7 @@ struct show_var_st init_vars[]= { {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG}, {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR}, {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS}, + {sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS}, {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS}, {sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS}, {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9313f8e2c1b..839b92e7e7f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -806,8 +806,9 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, for (table=thd->temporary_tables; table ; table=table->next) { - if (table->key_length == key_length+8 && - !memcmp(table->table_cache_key,key,key_length+8)) + if (table->key_length == key_length + TMP_TABLE_KEY_EXTRA && + !memcmp(table->table_cache_key, key, + key_length + TMP_TABLE_KEY_EXTRA)) { if (table->query_id == thd->query_id) { diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 0b338ebccb8..be50b48d264 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1025,9 +1025,38 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) for (; block_table != block_table_end; block_table++) { TABLE_LIST table_list; - bzero((char*) &table_list,sizeof(table_list)); + TABLE *tmptable; Query_cache_table *table = block_table->parent; + + /* + Check that we have not temporary tables with same names of tables + of this query. If we have such tables, we will not send data from + query cache, because temporary tables hide real tables by which + query in query cache was made. + */ + for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next) + { + if (tmptable->key_length - TMP_TABLE_KEY_EXTRA == table->key_len() && + !memcmp(tmptable->table_cache_key, table->data(), + table->key_len())) + { + DBUG_PRINT("qcache", + ("Temporary table detected: '%s.%s'", + table_list.db, table_list.alias)); + STRUCT_UNLOCK(&structure_guard_mutex); + /* + We should not store result of this query because it contain + temporary tables => assign following variable to make check + faster. + */ + thd->safe_to_cache_query=0; + BLOCK_UNLOCK_RD(query_block); + DBUG_RETURN(-1); + } + } + + bzero((char*) &table_list,sizeof(table_list)); table_list.db = table->db(); table_list.alias= table_list.real_name= table->table(); #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/sql_cache.h b/sql/sql_cache.h index fc458f39e29..c933a2349af 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -143,14 +143,14 @@ struct Query_cache_query struct Query_cache_table { char *tbl; - uint key_len; + uint32 key_len; uint8 table_type; inline char *db() { return (char *) data(); } inline char *table() { return tbl; } inline void table(char *table) { tbl= table; } - inline uint key_length() { return key_len; } - inline void key_length(uint len) { key_len= len; } + inline uint32 key_length() { return key_len; } + inline void key_length(uint32 len) { key_len= len; } inline uint8 type() { return table_type; } inline void type(uint8 t) { table_type= t; } inline gptr data() diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e061005ae61..d1f460d918e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2471,7 +2471,7 @@ unsent_create_error: if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN)) { net_printf(thd, ER_WRONG_TABLE_NAME, lex->name); - res=0; + res= 1; break; } if (!select_lex->db) |