From: Date: August 12 2008 12:59pm Subject: bzr commit into mysql-6.0 branch (monty:2682) List-Archive: http://lists.mysql.com/commits/51406 Message-Id: <20080812105956.4E7E51D58CF3@mysql.fi> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///home/my/mysql-6.0-maria/ 2682 Michael Widenius 2008-08-12 [merge] Merge with 5-1-Maria Fixed that test sute now works for all Maria tests modified: mysql-test/r/maria2.result mysql-test/t/maria2.test mysql-test/valgrind.supp sql/mdl.cc sql/sql_base.cc sql/sql_table.cc storage/maria/ha_maria.cc storage/maria/ma_extra.c storage/maria/ma_recovery.c storage/maria/ma_state.c storage/maria/ma_state.h per-file messages: mysql-test/r/maria2.result New test case mysql-test/t/maria2.test New test case mysql-test/valgrind.supp Removed duplicated code Fixed suppression to be more general to avoid warning on x32 sql/mdl.cc Fixed crashing bug when mysqld didn't start sql/sql_base.cc Fixed old wrong merge; extra() should be called when we are the only one that is using the table sql/sql_table.cc Changed extra() call to rename to tell storage engine that we don't need to keep any versioning information about the table anymore storage/maria/ha_maria.cc Automatic merge storage/maria/ma_extra.c Automatic merge Ensure that info->state_start is reset as part of EXTRA_RENAME storage/maria/ma_recovery.c Automatic merge storage/maria/ma_state.c Automatic merge storage/maria/ma_state.h Automatic merge === modified file 'mysql-test/r/maria2.result' --- a/mysql-test/r/maria2.result 2008-06-10 14:44:44 +0000 +++ b/mysql-test/r/maria2.result 2008-08-12 10:59:30 +0000 @@ -1,3 +1,4 @@ +drop table if exists t1,t2; CREATE TABLE t1 ( line BLOB, kind ENUM('po', 'pp', 'rr', 'dr', 'rd', 'ts', 'cl') NOT NULL DEFAULT 'po', @@ -16,3 +17,44 @@ check table t1 extended; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; +create table t1 (i int) engine=maria; +create table t2 (j int) engine=maria; +lock table t1 write, t2 read; +alter table t1 modify i int default 1; +insert into t1 values (2); +alter table t1 modify i bigint default 1; +select count(*) from t1; +count(*) +1 +select * from t1; +i +2 +unlock tables; +drop table t1,t2; +create table t1(id int, s char(1), unique(s)) engine=maria; +insert into t1 values(1,"a") on duplicate key update t1.id=t1.id+1; +insert into t1 values(1,"a") on duplicate key update t1.id=t1.id+1; +insert into t1 select 1,"a" on duplicate key update t1.id=t1.id+1; +select * from t1; +id s +3 a +replace into t1 select 1,"a"; +select * from t1; +id s +1 a +drop table t1; +create table t1 (pk int primary key, apk int unique, data int) engine=maria; +insert into t1 values (1, 1, 1), (4, 4, 4), (6, 6, 6); +load data concurrent infile '../std_data_ln/loaddata5.dat' replace into table t1 fields terminated by '' enclosed by '' ignore 1 lines (pk, apk); +select * from t1 order by pk; +pk apk data +1 1 1 +3 4 NULL +5 6 NULL +load data infile '../std_data_ln/loaddata5.dat' replace into table t1 fields terminated by '' enclosed by '' ignore 1 lines (pk, apk); +select * from t1 order by pk; +pk apk data +1 1 1 +3 4 NULL +5 6 NULL +drop table t1; === modified file 'mysql-test/t/maria2.test' --- a/mysql-test/t/maria2.test 2008-06-10 14:44:44 +0000 +++ b/mysql-test/t/maria2.test 2008-08-12 10:59:30 +0000 @@ -1,5 +1,10 @@ --source include/have_maria.inc +# Initialise +--disable_warnings +drop table if exists t1,t2; +--enable_warnings + # Test for BUG#36319 # "Maria: table is not empty but DELETE and SELECT find no rows" @@ -64,3 +69,43 @@ select count(*) from t1; select name from t1; check table t1 extended; drop table t1; + +# +# Testing of ALTER TABLE under lock tables +# + +create table t1 (i int) engine=maria; +create table t2 (j int) engine=maria; +lock table t1 write, t2 read; +alter table t1 modify i int default 1; +insert into t1 values (2); +# This caused a core dump +alter table t1 modify i bigint default 1; +select count(*) from t1; +select * from t1; +unlock tables; +drop table t1,t2; + +# +# test INSERT ON DUPLICATE KEY UPDATE +# + +create table t1(id int, s char(1), unique(s)) engine=maria; +insert into t1 values(1,"a") on duplicate key update t1.id=t1.id+1; +insert into t1 values(1,"a") on duplicate key update t1.id=t1.id+1; +insert into t1 select 1,"a" on duplicate key update t1.id=t1.id+1; +select * from t1; + +# test REPLACE SELECT +replace into t1 select 1,"a"; +select * from t1; +drop table t1; + +# test LOAD DATA INFILE REPLACE +create table t1 (pk int primary key, apk int unique, data int) engine=maria; +insert into t1 values (1, 1, 1), (4, 4, 4), (6, 6, 6); +load data concurrent infile '../std_data_ln/loaddata5.dat' replace into table t1 fields terminated by '' enclosed by '' ignore 1 lines (pk, apk); +select * from t1 order by pk; +load data infile '../std_data_ln/loaddata5.dat' replace into table t1 fields terminated by '' enclosed by '' ignore 1 lines (pk, apk); +select * from t1 order by pk; +drop table t1; === modified file 'mysql-test/valgrind.supp' --- a/mysql-test/valgrind.supp 2008-06-05 17:16:32 +0000 +++ b/mysql-test/valgrind.supp 2008-08-12 10:59:30 +0000 @@ -27,7 +27,7 @@ pthread allocate_tls memory loss Memcheck:Leak fun:calloc - obj:/lib64/ld*.so + obj:/lib*/ld*.so fun:_dl_allocate_tls fun:pthread_create* } @@ -388,40 +388,58 @@ } { - dlopen / ptread_cancel_init memory loss on Suse Linux 10.3 64 bit + dlopen / ptread_cancel_init memory loss on Suse Linux 10.3 32/64 bit Memcheck:Leak fun:*alloc - obj:/lib64/ld-*.so - obj:/lib64/ld-*.so - obj:/lib64/ld-*.so - obj:/lib64/ld-*.so - obj:/lib64/ld-*.so - obj:/lib64/ld-*.so - obj:/lib64/libc-*.so - obj:/lib64/ld-*.so - obj:/lib64/libc-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/libc-*.so + obj:/lib*/ld-*.so + obj:/lib*/libc-*.so fun:__libc_dlopen_mode fun:pthread_cancel_init fun:_Unwind_ForcedUnwind - } { - dlopen / ptread_cancel_init memory loss on Suse Linux 10.3 64 bit + dlopen / ptread_cancel_init memory loss on Suse Linux 10.3 32/64 bit Memcheck:Leak fun:*alloc - obj:/lib64/ld-*.so - obj:/lib64/ld-*.so - obj:/lib64/ld-*.so - obj:/lib64/ld-*.so - obj:/lib64/libc-*.so - obj:/lib64/ld-*.so - obj:/lib64/libc-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/libc-*.so + obj:/lib*/ld-*.so + obj:/lib*/libc-*.so fun:__libc_dlopen_mode fun:pthread_cancel_init fun:_Unwind_ForcedUnwind } +# +# Reading wrong addresses on SuSe Linux 10.3 32 bit +# + +{ + Reading wrong data in libc_dlopen + Memcheck:Addr4 + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/ld-*.so + obj:/lib*/libc-*.so + obj:/lib*/ld-*.so + obj:/lib*/libc-*.so + fun:__libc_dlopen_mode + fun:pthread_cancel_init +} # # These seem to be libc threading stuff, not related to MySQL code (allocations === modified file 'sql/mdl.cc' --- a/sql/mdl.cc 2008-06-20 13:11:20 +0000 +++ b/sql/mdl.cc 2008-08-12 10:59:30 +0000 @@ -19,6 +19,7 @@ #include #include +static bool mdl_initialized= 0; /** The lock context. Created internally for an acquired lock. @@ -115,6 +116,7 @@ extern "C" uchar *mdl_locks_key(const uc void mdl_init() { + mdl_initialized= 1; pthread_mutex_init(&LOCK_mdl, NULL); pthread_cond_init(&COND_mdl, NULL); hash_init(&mdl_locks, &my_charset_bin, 16 /* FIXME */, 0, 0, @@ -133,10 +135,14 @@ void mdl_init() void mdl_destroy() { - DBUG_ASSERT(!mdl_locks.records); - pthread_mutex_destroy(&LOCK_mdl); - pthread_cond_destroy(&COND_mdl); - hash_free(&mdl_locks); + if (mdl_initialized) + { + mdl_initialized= 0; + DBUG_ASSERT(!mdl_locks.records); + pthread_mutex_destroy(&LOCK_mdl); + pthread_cond_destroy(&COND_mdl); + hash_free(&mdl_locks); + } } === modified file 'sql/sql_base.cc' --- a/sql/sql_base.cc 2008-06-28 11:00:59 +0000 +++ b/sql/sql_base.cc 2008-08-12 10:59:30 +0000 @@ -2029,8 +2029,6 @@ bool wait_while_table_is_used(THD *thd, table->s->table_name.str, table->s, table->db_stat, table->s->version)); - (void) table->file->extra(function); - old_lock_type= table->reginfo.lock_type; mysql_lock_abort(thd, table, TRUE); /* end threads waiting on lock */ @@ -2045,6 +2043,8 @@ bool wait_while_table_is_used(THD *thd, tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, table->s->db.str, table->s->table_name.str); pthread_mutex_unlock(&LOCK_open); + /* extra() call must come only after all instances above are closed */ + (void) table->file->extra(function); DBUG_RETURN(FALSE); } === modified file 'sql/sql_table.cc' --- a/sql/sql_table.cc 2008-06-30 09:59:59 +0000 +++ b/sql/sql_table.cc 2008-08-12 10:59:30 +0000 @@ -5787,7 +5787,7 @@ mysql_fast_or_online_alter_table(THD *th Upgrade the shared metadata lock to exclusive and close all instances of the table in the TDC except those used in this thread. */ - if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) + if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME)) DBUG_RETURN(1); alter_table_manage_keys(table, table->file->indexes_are_disabled(), @@ -7011,7 +7011,6 @@ view_err: if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME)) goto err_new_table_cleanup; - close_all_tables_for_name(thd, table->s, new_name != table_name || new_db != db); === modified file 'storage/maria/ha_maria.cc' --- a/storage/maria/ha_maria.cc 2008-07-10 14:58:31 +0000 +++ b/storage/maria/ha_maria.cc 2008-08-12 10:59:30 +0000 @@ -1847,6 +1847,7 @@ bool ha_maria::is_crashed() const int ha_maria::update_row(const uchar * old_data, uchar * new_data) { + DBUG_ASSERT(file->lock.type != TL_WRITE_CONCURRENT_INSERT); ha_statistic_increment(&SSV::ha_update_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); @@ -1856,6 +1857,7 @@ int ha_maria::update_row(const uchar * o int ha_maria::delete_row(const uchar * buf) { + DBUG_ASSERT(file->lock.type != TL_WRITE_CONCURRENT_INSERT); ha_statistic_increment(&SSV::ha_delete_count); return maria_delete(file, buf); } @@ -2389,6 +2391,7 @@ THR_LOCK_DATA **ha_maria::store_lock(THD (lock_type == TL_IGNORE || file->lock.type == TL_UNLOCK)); if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK) { + const enum enum_sql_command sql_command= thd->lex->sql_command; /* We have to disable concurrent inserts for INSERT ... SELECT or INSERT/UPDATE/DELETE with sub queries if we are using statement based @@ -2397,24 +2400,33 @@ THR_LOCK_DATA **ha_maria::store_lock(THD */ if (lock_type <= TL_READ_HIGH_PRIORITY && !thd->current_stmt_binlog_row_based && - (thd->lex->sql_command != SQLCOM_SELECT && - thd->lex->sql_command != SQLCOM_LOCK_TABLES) && + (sql_command != SQLCOM_SELECT && + sql_command != SQLCOM_LOCK_TABLES) && (thd->options & OPTION_BIN_LOG) && mysql_bin_log.is_open()) lock_type= TL_READ_NO_INSERT; - else if (lock_type == TL_WRITE_CONCURRENT_INSERT && - (file->state->records == 0)) + else if (lock_type == TL_WRITE_CONCURRENT_INSERT) { + const enum enum_duplicates duplicates= thd->lex->duplicates; /* - Bulk insert may use repair, which will cause problems if other + Explanation for the 3 conditions below, in order: + + - Bulk insert may use repair, which will cause problems if other threads try to read/insert to the table: disable versioning. Note that our read of file->state->records is incorrect, as such variable may have changed when we come to start_bulk_insert() (worse case: we see != 0 so allow versioning, start_bulk_insert() sees 0 and uses repair). This is prevented because start_bulk_insert() will not try repair if we enabled versioning. + - INSERT SELECT ON DUPLICATE KEY UPDATE comes here with + TL_WRITE_CONCURRENT_INSERT but shouldn't because it can do + update/delete of a row and versioning doesn't support that + - same for LOAD DATA CONCURRENT REPLACE. */ - lock_type= TL_WRITE; + if ((file->state->records == 0) || + (sql_command == SQLCOM_INSERT_SELECT && duplicates == DUP_UPDATE) || + (sql_command == SQLCOM_LOAD && duplicates == DUP_REPLACE)) + lock_type= TL_WRITE; } file->lock.type= lock_type; } === modified file 'storage/maria/ma_extra.c' --- a/storage/maria/ma_extra.c 2008-06-26 05:18:28 +0000 +++ b/storage/maria/ma_extra.c 2008-08-12 10:59:30 +0000 @@ -322,6 +322,13 @@ int maria_extra(MARIA_HA *info, enum ha_ if (share->kfile.file >= 0) _ma_decrement_open_count(info); pthread_mutex_lock(&share->intern_lock); + if (info->trn) + { + _ma_remove_table_from_trnman(share, info->trn); + /* Ensure we don't point to the deleted data in trn */ + info->state= info->state_start= &share->state.state; + } + type= do_flush ? FLUSH_RELEASE : FLUSH_IGNORE_CHANGED; if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX, type, type)) === modified file 'storage/maria/ma_recovery.c' --- a/storage/maria/ma_recovery.c 2008-07-09 21:25:29 +0000 +++ b/storage/maria/ma_recovery.c 2008-08-12 10:59:30 +0000 @@ -3234,6 +3234,16 @@ void _ma_tmp_disable_logging_for_table(M /* if we disabled before writing the record, record wouldn't reach log */ share->now_transactional= FALSE; + + /* + Reset state pointers. This is needed as in ALTER table we may do + commit fllowed by _ma_renable_logging_for_table and then + info->state may point to a state that was deleted by + _ma_trnman_end_trans_hook() + */ + share->state.common= *info->state; + info->state= &share->state.common; + /* Some code in ma_blockrec.c assumes a trn even if !now_transactional but in this case it only reads trn->rec_lsn, which has to be LSN_IMPOSSIBLE and @@ -3275,6 +3285,7 @@ my_bool _ma_reenable_logging_for_table(M in not transactional mode */ _ma_copy_nontrans_state_information(info); + _ma_reset_history(info->s); if (flush_pages) { === modified file 'storage/maria/ma_state.c' --- a/storage/maria/ma_state.c 2008-07-05 11:03:21 +0000 +++ b/storage/maria/ma_state.c 2008-07-12 14:14:28 +0000 @@ -371,7 +371,7 @@ my_bool _ma_trnman_end_trans_hook(TRN *t MARIA_STATE_HISTORY *history; pthread_mutex_lock(&share->intern_lock); - if (active_transactions && + if (active_transactions && share->now_transactional && trnman_exists_active_transactions(share->state_history->trid, trn->commit_trid, 1)) { @@ -415,6 +415,35 @@ my_bool _ma_trnman_end_trans_hook(TRN *t } +/** + Remove table from trnman_list + + @notes + This is used when we unlock a table from a group of locked tables + just before doing a rename or drop table. +*/ + +void _ma_remove_table_from_trnman(MARIA_SHARE *share, TRN *trn) +{ + MARIA_USED_TABLES *tables, **prev; + + for (prev= (MARIA_USED_TABLES**) &trn->used_tables, tables= *prev; + tables; + tables= *prev) + { + if (tables->share == share) + { + *prev= tables->next; + my_free(tables, MYF(0)); + } + else + prev= &tables->next; + } +} + + + + /**************************************************************************** The following functions are called by thr_lock() in threaded applications for transactional tables. @@ -509,6 +538,23 @@ void _ma_copy_nontrans_state_information } +void _ma_reset_history(MARIA_SHARE *share) +{ + MARIA_STATE_HISTORY *history, *next; + + share->state_history->trid= 0; /* Visibly by all */ + share->state_history->state= share->state.state; + history= share->state_history->next; + share->state_history->next= 0; + + for (; history; history= next) + { + next= history->next; + my_free(history, MYF(0)); + } +} + + /**************************************************************************** Virtual functions to check if row is visible ****************************************************************************/ === modified file 'storage/maria/ma_state.h' --- a/storage/maria/ma_state.h 2008-07-05 11:03:21 +0000 +++ b/storage/maria/ma_state.h 2008-07-12 14:14:28 +0000 @@ -77,3 +77,5 @@ my_bool _ma_row_visible_always(MARIA_HA my_bool _ma_row_visible_non_transactional_table(MARIA_HA *info); my_bool _ma_row_visible_transactional_table(MARIA_HA *info); void _ma_remove_not_visible_states_with_lock(struct st_maria_share *share); +void _ma_remove_table_from_trnman(struct st_maria_share *share, TRN *trn); +void _ma_reset_history(struct st_maria_share *share);