#At bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-maria/
2657 Michael Widenius 2008-07-12
Fixing bug when using alter table on locked maria table
Reset history when we reenable logging for transactional tables (safety fix)
modified:
mysql-test/r/maria2.result
mysql-test/t/maria2.test
mysql-test/valgrind.supp
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 results
mysql-test/t/maria2.test
Added test case for alter table on locked maria table
mysql-test/valgrind.supp
Added suppression rules for warnings in libc / libld
storage/maria/ma_extra.c
Remove table from trnman list if we are going to drop or rename it; We don't want not existing shares in the list when we do commit!
storage/maria/ma_recovery.c
Ensure that info->state don't point to history event when we disable logging for a table; This is needed as alter table will first do commit and then unlock, which would cause us to access a non existing object when we reenable logging.
Reset history when we reenable logging (safety fix)
storage/maria/ma_state.c
Do less work when share->now_transactional is not set. (Safety fix)
Added function to remove shares to be deleted from trnman->used_tables
Added function to reset history to current context
storage/maria/ma_state.h
Prototypes for new function
=== 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-07-12 14:14:28 +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,16 @@ 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
+drop table t1,t2;
=== 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-07-12 14:14:28 +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,19 @@ 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;
+drop table t1,t2;
+
=== modified file 'mysql-test/valgrind.supp'
--- a/mysql-test/valgrind.supp 2008-06-04 09:39:54 +0000
+++ b/mysql-test/valgrind.supp 2008-07-12 14:14:28 +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 '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-07-12 14:14:28 +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= &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-06-26 09:32:22 +0000
+++ b/storage/maria/ma_recovery.c 2008-07-12 14:14:28 +0000
@@ -3214,6 +3214,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
@@ -3255,6 +3265,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);