diff --git a/.bzrignore b/.bzrignore index 74c81c48e05..57209c72b87 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1143,3 +1143,4 @@ sql/db.opt ./_CPack_Packages ./install_manifest_*.txt typescript +mysql-test/collections/default.release.done diff --git a/mysql-test/r/myisam-metadata.result b/mysql-test/r/myisam-metadata.result new file mode 100644 index 00000000000..5192253d5d1 --- /dev/null +++ b/mysql-test/r/myisam-metadata.result @@ -0,0 +1,12 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( +id INT PRIMARY KEY, +a VARCHAR(100), +INDEX(a) +) ENGINE=MyISAM; +ALTER TABLE t1 DISABLE KEYS; +ALTER TABLE t1 ENABLE KEYS; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Dynamic 100000 27 # # # 0 NULL # # # latin1_swedish_ci NULL +DROP TABLE t1; diff --git a/mysql-test/suite/rpl/r/replace.result b/mysql-test/suite/rpl/r/replace.result new file mode 100644 index 00000000000..855c54ef8fa --- /dev/null +++ b/mysql-test/suite/rpl/r/replace.result @@ -0,0 +1,22 @@ +include/master-slave.inc +[connection master] +drop table if exists t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1 (pr_id int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, pr_page int(11) NOT NULL, pr_type varbinary(60) NOT NULL, test int, UNIQUE KEY pr_pagetype (pr_page,pr_type)) ENGINE=myisam AUTO_INCREMENT=136; +insert into t1 (pr_page, pr_type, test) values(1,"one",0),(2,"two",0); +select * from t1; +pr_id pr_page pr_type test +136 1 one 0 +137 2 two 0 +replace into t1 (pr_page, pr_type,test) values(1,"one",2); +select * from t1; +pr_id pr_page pr_type test +138 1 one 2 +137 2 two 0 +select * from t1; +pr_id pr_page pr_type test +138 1 one 2 +137 2 two 0 +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/replace.test b/mysql-test/suite/rpl/t/replace.test new file mode 100644 index 00000000000..36afda0d927 --- /dev/null +++ b/mysql-test/suite/rpl/t/replace.test @@ -0,0 +1,24 @@ +# +# Test of REPLACE with replication +# + +source include/master-slave.inc; + +# +# Test of doing replace on unique key on table with auto_increment +# + +drop table if exists t1; +CREATE TABLE t1 (pr_id int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, pr_page int(11) NOT NULL, pr_type varbinary(60) NOT NULL, test int, UNIQUE KEY pr_pagetype (pr_page,pr_type)) ENGINE=myisam AUTO_INCREMENT=136; +insert into t1 (pr_page, pr_type, test) values(1,"one",0),(2,"two",0); +select * from t1; +replace into t1 (pr_page, pr_type,test) values(1,"one",2); +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +drop table t1; + +# End of 5.5 tests +--source include/rpl_end.inc diff --git a/mysql-test/t/myisam-metadata.test b/mysql-test/t/myisam-metadata.test new file mode 100644 index 00000000000..c5327aa3a71 --- /dev/null +++ b/mysql-test/t/myisam-metadata.test @@ -0,0 +1,49 @@ +# +# Test bugs in MyISAM that may cause problems for metadata +# + +--source include/big_test.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +# +# LP:989055 - Querying myisam table metadata may corrupt the table +# + +CREATE TABLE t1 ( + id INT PRIMARY KEY, + a VARCHAR(100), + INDEX(a) +) ENGINE=MyISAM; +ALTER TABLE t1 DISABLE KEYS; + +let $1=100000; +--disable_query_log +while ($1) +{ + eval insert into t1 values($1, "line number $1"); + dec $1; +} +--enable_query_log + +--connect(con1,localhost,root,,) +--send + ALTER TABLE t1 ENABLE KEYS; + +--connection default +--let $wait_timeout=10 +--let $show_statement= SHOW PROCESSLIST +--let $field= State +--let $condition= = 'Repair by sorting' +--source include/wait_show_condition.inc + +--replace_column 7 # 8 # 9 # 12 # 13 # 14 # +SHOW TABLE STATUS LIKE 't1'; + +--connection con1 +--reap +--connection default +--disconnect con1 +DROP TABLE t1; diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 4f503def01d..222279cc8ff 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -71,6 +71,7 @@ Usage: $0 [OPTIONS] --defaults-extra-file=FILE Also use defaults from the specified file --ledir=DIRECTORY Look for mysqld in the specified directory --open-files-limit=LIMIT Limit the number of open files + --crash-script=FILE Script to call when mysqld crashes --timezone=TZ Set the system timezone --malloc-lib=LIB Preload shared library LIB if available --mysqld=FILE Use the specified file as mysqld @@ -202,6 +203,7 @@ parse_arguments() { optname_subst=`echo "$optname" | sed 's/_/-/g'` arg=`echo $arg | sed "s/^$optname/$optname_subst/"` case "$arg" in + --crash-script=*) CRASH_SCRIPT="$val" ;; # these get passed explicitly to mysqld --basedir=*) MY_BASEDIR_VERSION="$val" ;; --datadir=*|--data=*) DATADIR="$val" ;; @@ -799,7 +801,7 @@ have_sleep=1 while true do - rm -f $safe_mysql_unix_port "$pid_file" # Some extra safety + rm -f "$pid_file" # Some extra safety start_time=`date +%M%S` @@ -874,6 +876,11 @@ do done fi log_notice "mysqld restarted" + if test -n "$CRASH_SCRIPT" + then + crash_script_output=`$CRASH_SCRIPT 2>&1` + log_error "$crash_script_output" + fi done log_notice "mysqld from pid file $pid_file ended" diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 872ab8a54ca..d0e0c29a432 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7298,7 +7298,7 @@ static int mysql_init_variables(void) log_error_file_ptr= log_error_file; protocol_version= PROTOCOL_VERSION; what_to_log= ~ (1L << (uint) COM_TIME); - refresh_version= 1L; /* Increments on each reload */ + refresh_version= 2L; /* Increments on each reload. 0 and 1 are reserved */ executed_events= 0; global_query_id= thread_id= 1L; my_atomic_rwlock_init(&global_query_id_lock); diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 631c4271eb5..4414a077df8 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -87,6 +87,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, const char **ext; MY_STAT stat_info; Open_table_context ot_ctx(thd, (MYSQL_OPEN_IGNORE_FLUSH | + MYSQL_OPEN_FOR_REPAIR | MYSQL_OPEN_HAS_MDL_LOCK | MYSQL_LOCK_IGNORE_TIMEOUT)); DBUG_ENTER("prepare_for_repair"); @@ -197,7 +198,8 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, */ pos_in_locked_tables= table->pos_in_locked_tables; if (wait_while_table_is_used(thd, table, - HA_EXTRA_PREPARE_FOR_FORCED_CLOSE)) + HA_EXTRA_PREPARE_FOR_FORCED_CLOSE, + TDC_RT_REMOVE_NOT_OWN_AND_MARK_NOT_USABLE)) goto end; /* Close table but don't remove from locked list */ close_all_tables_for_name(thd, table_list->table->s, @@ -589,8 +591,10 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, */ if (lock_type == TL_WRITE && !table->table->s->tmp_table) { + table->table->s->protect_against_usage(); if (wait_while_table_is_used(thd, table->table, - HA_EXTRA_PREPARE_FOR_RENAME)) + HA_EXTRA_PREPARE_FOR_RENAME, + TDC_RT_REMOVE_NOT_OWN_AND_MARK_NOT_USABLE)) goto err; DEBUG_SYNC(thd, "after_admin_flush"); /* Flush entries in the query cache involving this table. */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 277e07b9c49..46b936a6b21 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1068,7 +1068,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, if (share) { kill_delayed_threads_for_table(share); - /* tdc_remove_table() also sets TABLE_SHARE::version to 0. */ + /* tdc_remove_table() calls share->remove_from_cache_at_close() */ tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED, table->db, table->table_name, TRUE); found=1; @@ -2327,7 +2327,8 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *db, */ bool wait_while_table_is_used(THD *thd, TABLE *table, - enum ha_extra_function function) + enum ha_extra_function function, + enum_tdc_remove_table_type remove_type) { DBUG_ENTER("wait_while_table_is_used"); DBUG_PRINT("enter", ("table: '%s' share: 0x%lx db_stat: %u version: %lu", @@ -2338,7 +2339,7 @@ bool wait_while_table_is_used(THD *thd, TABLE *table, table->mdl_ticket, thd->variables.lock_wait_timeout)) DBUG_RETURN(TRUE); - tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, + tdc_remove_table(thd, remove_type, table->s->db.str, table->s->table_name.str, FALSE); /* extra() call must come only after all instances above are closed */ @@ -3084,7 +3085,9 @@ retry_share: goto err_unlock; } - if (!(flags & MYSQL_OPEN_IGNORE_FLUSH)) + if (!(flags & MYSQL_OPEN_IGNORE_FLUSH) || + (share->protected_against_usage() && + !(flags & MYSQL_OPEN_FOR_REPAIR))) { if (share->has_old_version()) { @@ -9376,6 +9379,7 @@ void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, TABLE *table; TABLE_SHARE *share; DBUG_ENTER("tdc_remove_table"); + DBUG_PRINT("enter",("name: %s remove_type: %d", table_name, remove_type)); if (! has_lock) mysql_mutex_lock(&LOCK_open); @@ -9401,7 +9405,8 @@ void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, { DBUG_ASSERT(share->used_tables.is_empty()); } - else if (remove_type == TDC_RT_REMOVE_NOT_OWN) + else if (remove_type == TDC_RT_REMOVE_NOT_OWN || + remove_type == TDC_RT_REMOVE_NOT_OWN_AND_MARK_NOT_USABLE) { I_P_List_iterator