diff options
author | unknown <bell@production.mysql.com> | 2006-03-17 00:56:47 +0100 |
---|---|---|
committer | unknown <bell@production.mysql.com> | 2006-03-17 00:56:47 +0100 |
commit | aa3411f54b2d5e2b6069b122085926f771133437 (patch) | |
tree | 1ebcd02409c151b4a2447ddb92db49526cd9b6b2 | |
parent | 48e23ec8627007a330a37ff9925e11fdc94b1281 (diff) | |
parent | bb69d16d6b06aefeba7b3caf1b220edf2ffe44f0 (diff) | |
download | mariadb-git-aa3411f54b2d5e2b6069b122085926f771133437.tar.gz |
Merge abelkin@bk-internal.mysql.com:/home/bk/mysql-5.0
into production.mysql.com:/usersnfs/abelkin/work-qc-5.0
-rw-r--r-- | mysql-test/r/query_cache_notembedded.result | 30 | ||||
-rw-r--r-- | mysql-test/t/query_cache_notembedded.test | 40 | ||||
-rw-r--r-- | sql/sql_insert.cc | 51 | ||||
-rw-r--r-- | sql/sql_parse.cc | 13 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 25 |
5 files changed, 136 insertions, 23 deletions
diff --git a/mysql-test/r/query_cache_notembedded.result b/mysql-test/r/query_cache_notembedded.result index 77fa198eb80..4226738725a 100644 --- a/mysql-test/r/query_cache_notembedded.result +++ b/mysql-test/r/query_cache_notembedded.result @@ -314,4 +314,34 @@ drop procedure f2; drop procedure f3; drop procedure f4; drop table t1; +reset query cache; +drop function if exists f1; +create table t1 (id int); +create function f1 () +returns int +begin +declare i_var int; +set i_var = sleep(3); +insert into t1 values(3); +set i_var = sleep(3); +return 0; +end;| + select f1(); +select sleep(4); +sleep(4) +0 +select * from t1; +id +3 +f1() +0 +select * from t1; +id +3 +reset query cache; +select * from t1; +id +3 +drop table t1; +drop function f1; set GLOBAL query_cache_size=0; diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test index 5e1ab7051e5..97be9f9f7ca 100644 --- a/mysql-test/t/query_cache_notembedded.test +++ b/mysql-test/t/query_cache_notembedded.test @@ -180,5 +180,45 @@ drop procedure f3; drop procedure f4; drop table t1; +# +# bug#14767: INSERT in SF + concurrent SELECT with query cache +# +reset query cache; +--disable_warnings +drop function if exists f1; +--enable_warnings +create table t1 (id int); +delimiter |; +create function f1 () + returns int +begin + declare i_var int; + set i_var = sleep(3); + insert into t1 values(3); + set i_var = sleep(3); + return 0; +end;| +delimiter ;| + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); + +connection con1; +send select f1(); +connection con2; +select sleep(4); +select * from t1; +connection con1; +reap; +connection con2; +# This gives wrong result i.e. 't' table seems to be empty +select * from t1; +reset query cache; +select * from t1; +drop table t1; +drop function f1; +disconnect con1; +disconnect con2; +connection default; set GLOBAL query_cache_size=0; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index eb74144c1ea..b6ff0ecc216 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -258,6 +258,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->security_ctx->master_access & SUPER_ACL)); bool transactional_table, joins_freed= FALSE; + bool changed; uint value_count; ulong counter = 1; ulonglong id; @@ -544,32 +545,30 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, else if (table->next_number_field && info.copied) id=table->next_number_field->val_int(); // Return auto_increment value - /* - Invalidate the table in the query cache if something changed. - For the transactional algorithm to work the invalidation must be - before binlog writing and ha_autocommit_or_rollback - */ - if (info.copied || info.deleted || info.updated) - { - query_cache_invalidate3(thd, table_list, 1); - } - transactional_table= table->file->has_transactions(); - if ((info.copied || info.deleted || info.updated) && - (error <= 0 || !transactional_table)) + if ((changed= (info.copied || info.deleted || info.updated))) { - if (mysql_bin_log.is_open()) + /* + Invalidate the table in the query cache if something changed. + For the transactional algorithm to work the invalidation must be + before binlog writing and ha_autocommit_or_rollback + */ + query_cache_invalidate3(thd, table_list, 1); + if (error <= 0 || !transactional_table) { - if (error <= 0) - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_table, FALSE); - if (mysql_bin_log.write(&qinfo) && transactional_table) - error=1; + if (mysql_bin_log.is_open()) + { + if (error <= 0) + thd->clear_error(); + Query_log_event qinfo(thd, thd->query, thd->query_length, + transactional_table, FALSE); + if (mysql_bin_log.write(&qinfo) && transactional_table) + error=1; + } + if (!transactional_table) + thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } - if (!transactional_table) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } if (transactional_table) error=ha_autocommit_or_rollback(thd,error); @@ -577,6 +576,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (thd->lock) { mysql_unlock_tables(thd, 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->lock=0; } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d9f5499f362..f9d04fc873e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3314,6 +3314,19 @@ end_with_restore_list: select_lex->context.table_list= select_lex->context.first_name_resolution_table= second_table; res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE); + /* + Invalidate the table in the query cache if something changed + after unlocking when changes become visible. + TODO: this is workaround. right way will be move invalidating in + the unlock procedure. + */ + if (first_table->lock_type == TL_WRITE_CONCURRENT_INSERT && + thd->lock) + { + mysql_unlock_tables(thd, thd->lock); + query_cache_invalidate3(thd, first_table, 1); + thd->lock=0; + } delete result; } /* revert changes for SP */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 03da97b91c9..ddc267eb970 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6068,7 +6068,19 @@ replace: ; insert_lock_option: - /* empty */ { $$= TL_WRITE_CONCURRENT_INSERT; } + /* empty */ + { +#ifdef HAVE_QUERY_CACHE + /* + If it is SP we do not allow insert optimisation whan result of + insert visible only after the table unlocking but everyone can + read table. + */ + $$= (Lex->sphead ? TL_WRITE :TL_WRITE_CONCURRENT_INSERT); +#else + $$= TL_WRITE_CONCURRENT_INSERT; +#endif + } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; } | DELAYED_SYM { $$= TL_WRITE_DELAYED; } | HIGH_PRIORITY { $$= TL_WRITE; } @@ -6925,7 +6937,16 @@ opt_local: load_data_lock: /* empty */ { $$= YYTHD->update_lock_default; } - | CONCURRENT { $$= TL_WRITE_CONCURRENT_INSERT ; } + | CONCURRENT + { +#ifdef HAVE_QUERY_CACHE + /* + Ignore this option in SP to avoid problem with query cache + */ + if (Lex->sphead != 0) +#endif + $$= TL_WRITE_CONCURRENT_INSERT; + } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }; |