diff --git a/mysql-test/extra/rpl_tests/rpl_failed_optimize.test b/mysql-test/extra/rpl_tests/rpl_failed_optimize.test index 598f9746fab..0c537ee188d 100644 --- a/mysql-test/extra/rpl_tests/rpl_failed_optimize.test +++ b/mysql-test/extra/rpl_tests/rpl_failed_optimize.test @@ -17,3 +17,8 @@ OPTIMIZE TABLE non_existing; sync_slave_with_master; # End of 4.1 tests + +connection master; +select * from t1; +commit; +drop table t1; diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index 56601d9236a..f2da89355f7 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -218,7 +218,8 @@ sub mtr_report_stats ($) { # We report different types of problems in order foreach my $pattern ( "^Warning:", "^Error:", "^==.* at 0x", "InnoDB: Warning", "missing DBUG_RETURN", - "mysqld: Warning") + "mysqld: Warning", + "Attempting backtrace", "Assertion .* failed" ) { foreach my $errlog ( sort glob("$::opt_vardir/log/*.err") ) { @@ -232,7 +233,8 @@ sub mtr_report_stats ($) { # Skip some non fatal warnings from the log files if ( /Warning:\s+Table:.* on (delete|rename)/ or /Warning:\s+Setting lower_case_table_names=2/ or - /Warning:\s+One can only use the --user.*root/ ) + /Warning:\s+One can only use the --user.*root/ or + /InnoDB: Warning: we did not need to do crash recovery/) { next; # Skip these lines } diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 24e88d1e5e3..f56099f3a49 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -1073,13 +1073,13 @@ report_stats () { # $RM -f $MY_LOG_DIR/warnings $MY_LOG_DIR/warnings.tmp # Remove some non fatal warnings from the log files - $SED -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' \ + $SED -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' -e 's|InnoDB: Warning: we did not need to do crash recovery||g' \ $MY_LOG_DIR/*.err \ | $SED -e 's!Warning: Table:.* on rename!!g' \ > $MY_LOG_DIR/warnings.tmp # Find errors - for i in "^Warning:" "^Error:" "^==.* at 0x" "InnoDB: Warning" "missing DBUG_RETURN" "mysqld: Warning" + for i in "^Warning:" "^Error:" "^==.* at 0x" "InnoDB: Warning" "missing DBUG_RETURN" "mysqld: Warning" "Attempting backtrace" "Assertion .* failed" do if $GREP "$i" $MY_LOG_DIR/warnings.tmp >> $MY_LOG_DIR/warnings then diff --git a/mysql-test/r/exampledb.result b/mysql-test/r/exampledb.result index 9bfb77c1c0b..6eea24e2e1f 100644 --- a/mysql-test/r/exampledb.result +++ b/mysql-test/r/exampledb.result @@ -1,3 +1,5 @@ +drop database if exists events_test; +drop database if exists events_test2; drop table if exists t1; CREATE TABLE t1 ( Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 03e9525c977..7ae87e42b8c 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -3457,3 +3457,10 @@ a drop table t2, t1; create table t1 (g geometry not null, spatial gk(g)) engine=innodb; ERROR HY000: The used table type doesn't support SPATIAL indexes +CREATE TABLE t1 ( a int ) ENGINE=innodb; +BEGIN; +INSERT INTO t1 VALUES (1); +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +DROP TABLE t1; diff --git a/mysql-test/r/rpl_failed_optimize.result b/mysql-test/r/rpl_failed_optimize.result index fd711f89222..ec0b3856ae7 100644 --- a/mysql-test/r/rpl_failed_optimize.result +++ b/mysql-test/r/rpl_failed_optimize.result @@ -18,3 +18,8 @@ Table Op Msg_type Msg_text test.non_existing optimize error Table 'test.non_existing' doesn't exist Warnings: Error 1146 Table 'test.non_existing' doesn't exist +select * from t1; +a +1 +commit; +drop table t1; diff --git a/mysql-test/t/exampledb.test b/mysql-test/t/exampledb.test index 946d25325dc..fbb2a18f344 100644 --- a/mysql-test/t/exampledb.test +++ b/mysql-test/t/exampledb.test @@ -5,6 +5,10 @@ -- source include/have_exampledb.inc --disable_warnings +# Clean up if event's test fails +drop database if exists events_test; +drop database if exists events_test2; + drop table if exists t1; --enable_warnings diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 820c7872b73..92e060eed92 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -2500,3 +2500,13 @@ drop table t2, t1; # --error ER_TABLE_CANT_HANDLE_SPKEYS create table t1 (g geometry not null, spatial gk(g)) engine=innodb; + +# +# Test optimize on table with open transaction +# + +CREATE TABLE t1 ( a int ) ENGINE=innodb; +BEGIN; +INSERT INTO t1 VALUES (1); +OPTIMIZE TABLE t1; +DROP TABLE t1; diff --git a/sql/handler.cc b/sql/handler.cc index 483bf049177..b9ef05a33c2 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3264,10 +3264,11 @@ int handler::ha_external_lock(THD *thd, int lock_type) locking combined with row-based replication needs to be looked over. Ideally, no such special handling should be needed. */ - switch (thd->lex->sql_command) - { + switch (thd->lex->sql_command) { case SQLCOM_TRUNCATE: case SQLCOM_ALTER_TABLE: + case SQLCOM_OPTIMIZE: + case SQLCOM_REPAIR: DBUG_RETURN(0); default: break; diff --git a/sql/log.cc b/sql/log.cc index 5ab855261ce..7c8f314bc08 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2879,23 +2879,27 @@ bool MYSQL_LOG::write(Log_event *event_info) binlog_trx_data *const trx_data= (binlog_trx_data*) thd->ha_data[binlog_hton.slot]; IO_CACHE *trans_log= &trx_data->trans_log; + bool trans_log_in_use= my_b_tell(trans_log) != 0; - if (event_info->get_cache_stmt() && !my_b_tell(trans_log)) + if (event_info->get_cache_stmt() && !trans_log_in_use) trans_register_ha(thd, - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN), + (thd->options & + (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)), &binlog_hton); - - if (event_info->get_cache_stmt() || my_b_tell(trans_log)) + if (event_info->get_cache_stmt() || trans_log_in_use) + { + DBUG_PRINT("info", ("Using trans_log")); file= trans_log; + } /* - Note: as Mats suggested, for all the cases above where we write to + TODO as Mats suggested, for all the cases above where we write to trans_log, it sounds unnecessary to lock LOCK_log. We should rather test first if we want to write to trans_log, and if not, lock - LOCK_log. TODO. + LOCK_log. */ } #endif - DBUG_PRINT("info",("event type=%d",event_info->get_type_code())); + DBUG_PRINT("info",("event type: %d",event_info->get_type_code())); /* No check for auto events flag here - this write method should diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 8c27db05a49..93db68d1b50 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -558,6 +558,7 @@ enum enum_mysql_completiontype { }; bool begin_trans(THD *thd); +bool end_active_trans(THD *thd); int end_trans(THD *thd, enum enum_mysql_completiontype completion); Item *negate_expression(THD *thd, Item *expr); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 010245cc077..77d2b165881 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -288,13 +288,13 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, if (!(share= alloc_table_share(table_list, key, key_length))) { -#ifdef NOT_YET +#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3 pthread_mutex_unlock(&LOCK_open); #endif DBUG_RETURN(0); } -#ifdef NOT_YET +#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3 // We need a write lock to be able to add a new entry pthread_mutex_unlock(&LOCK_open); pthread_mutex_lock(&LOCK_open); @@ -331,19 +331,19 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, if (my_hash_insert(&table_def_cache, (byte*) share)) { -#ifdef NOT_YET +#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3 pthread_mutex_unlock(&LOCK_open); (void) pthread_mutex_unlock(&share->mutex); #endif free_table_share(share); DBUG_RETURN(0); // return error } -#ifdef NOT_YET +#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3 pthread_mutex_unlock(&LOCK_open); #endif if (open_table_def(thd, share, db_flags)) { -#ifdef NOT_YET +#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3 /* No such table or wrong table definition file Lock first the table cache and then the mutex. @@ -372,7 +372,7 @@ found: /* We must do a lock to ensure that the structure is initialized */ (void) pthread_mutex_lock(&share->mutex); -#ifdef NOT_YET +#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3 pthread_mutex_unlock(&LOCK_open); #endif if (share->error) @@ -540,7 +540,7 @@ void release_table_share(TABLE_SHARE *share, enum release_type type) DBUG_VOID_RETURN; -#ifdef NOT_YET +#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3 if (to_be_deleted) { /* @@ -1069,7 +1069,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) handled either before writing a query log event (inside binlog_query()) or when preparing a pending event. */ - thd->binlog_flush_pending_rows_event(true); + thd->binlog_flush_pending_rows_event(TRUE); mysql_unlock_tables(thd, thd->lock); thd->lock=0; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 0173b15ea68..6166771e5d1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2688,8 +2688,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, DBUG_ENTER("THD::binlog_query"); DBUG_ASSERT(query && mysql_bin_log.is_open()); - switch (qtype) - { + switch (qtype) { case THD::MYSQL_QUERY_TYPE: /* Using this query type is a conveniece hack, since we have been diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1846660655b..8ee78578631 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -137,7 +137,7 @@ static void unlock_locked_tables(THD *thd) } -static bool end_active_trans(THD *thd) +bool end_active_trans(THD *thd) { int error=0; DBUG_ENTER("end_active_trans"); @@ -2961,8 +2961,7 @@ end_with_restore_list: thd->enable_slow_log= opt_log_slow_admin_statements; if (end_active_trans(thd)) goto error; - else - res = mysql_create_index(thd, first_table, lex->key_list); + res= mysql_create_index(thd, first_table, lex->key_list); break; #ifdef HAVE_REPLICATION @@ -3069,18 +3068,16 @@ end_with_restore_list: /* ALTER TABLE ends previous transaction */ if (end_active_trans(thd)) goto error; - else - { - thd->enable_slow_log= opt_log_slow_admin_statements; - res= mysql_alter_table(thd, select_lex->db, lex->name, - &lex->create_info, - first_table, lex->create_list, - lex->key_list, - select_lex->order_list.elements, - (ORDER *) select_lex->order_list.first, - lex->duplicates, lex->ignore, &lex->alter_info, - 1); - } + + thd->enable_slow_log= opt_log_slow_admin_statements; + res= mysql_alter_table(thd, select_lex->db, lex->name, + &lex->create_info, + first_table, lex->create_list, + lex->key_list, + select_lex->order_list.elements, + (ORDER *) select_lex->order_list.first, + lex->duplicates, lex->ignore, &lex->alter_info, + 1); break; } #endif /*DONT_ALLOW_SHOW_COMMANDS*/ @@ -3207,7 +3204,7 @@ end_with_restore_list: check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; - res = mysql_analyze_table(thd, first_table, &lex->check_opt); + res= mysql_analyze_table(thd, first_table, &lex->check_opt); /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) { @@ -3512,8 +3509,7 @@ end_with_restore_list: goto error; /* purecov: inspected */ if (end_active_trans(thd)) goto error; - else - res = mysql_drop_index(thd, first_table, &lex->alter_info); + res= mysql_drop_index(thd, first_table, &lex->alter_info); break; case SQLCOM_SHOW_PROCESSLIST: if (!thd->security_ctx->priv_user[0] && diff --git a/sql/sql_table.cc b/sql/sql_table.cc index d4ed25db2f8..f890f504952 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3898,6 +3898,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, int result_code; DBUG_ENTER("mysql_admin_table"); + if (end_active_trans(thd)) + DBUG_RETURN(1); field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2)); item->maybe_null = 1; field_list.push_back(item = new Item_empty_string("Op", 10)); @@ -3948,6 +3950,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, { switch ((*prepare_func)(thd, table, check_opt)) { case 1: // error, message written to net + ha_autocommit_or_rollback(thd, 1); close_thread_tables(thd); continue; case -1: // error, message could be written to net @@ -3989,6 +3992,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, View opening can be interrupted in the middle of process so some tables can be left opening */ + ha_autocommit_or_rollback(thd, 1); close_thread_tables(thd); if (protocol->write()) goto err; @@ -4013,6 +4017,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY), table_name); protocol->store(buff, length, system_charset_info); + ha_autocommit_or_rollback(thd, 0); close_thread_tables(thd); table->table=0; // For query cache if (protocol->write()) @@ -4058,6 +4063,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, (table->table->file->ha_check_for_upgrade(check_opt) == HA_ADMIN_NEEDS_ALTER)) { + ha_autocommit_or_rollback(thd, 1); close_thread_tables(thd); tmp_disable_binlog(thd); // binlogging is done by caller if wanted result_code= mysql_recreate_table(thd, table, 0); @@ -4144,6 +4150,7 @@ send_result_message: "try with alter", so here we close the table, do an ALTER TABLE, reopen the table and do ha_innobase::analyze() on it. */ + ha_autocommit_or_rollback(thd, 0); close_thread_tables(thd); TABLE_LIST *save_next_local= table->next_local, *save_next_global= table->next_global; @@ -4151,6 +4158,7 @@ send_result_message: tmp_disable_binlog(thd); // binlogging is done by caller if wanted result_code= mysql_recreate_table(thd, table, 0); reenable_binlog(thd); + ha_autocommit_or_rollback(thd, 0); close_thread_tables(thd); if (!result_code) // recreation went ok { @@ -4238,6 +4246,7 @@ send_result_message: query_cache_invalidate3(thd, table->table, 0); } } + ha_autocommit_or_rollback(thd, 0); close_thread_tables(thd); table->table=0; // For query cache if (protocol->write()) @@ -4246,7 +4255,9 @@ send_result_message: send_eof(thd); DBUG_RETURN(FALSE); + err: + ha_autocommit_or_rollback(thd, 1); close_thread_tables(thd); // Shouldn't be needed if (table) table->table=0; @@ -4701,7 +4712,9 @@ mysql_discard_or_import_tablespace(THD *thd, if (error) goto err; write_bin_log(thd, FALSE, thd->query, thd->query_length); + err: + ha_autocommit_or_rollback(thd, error); close_thread_tables(thd); thd->tablespace_op=FALSE; @@ -6388,7 +6401,8 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, } -bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) +bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, + HA_CHECK_OPT *check_opt) { TABLE_LIST *table; List field_list;