1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Fixing bug when using alter table on locked maria table

Reset history when we reenable logging for transactional tables (safety fix)

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
This commit is contained in:
Michael Widenius
2008-07-12 17:14:28 +03:00
parent 7f02282404
commit 50fa1eb8b5
7 changed files with 140 additions and 21 deletions

View File

@@ -1,3 +1,4 @@
drop table if exists t1,t2;
CREATE TABLE t1 ( CREATE TABLE t1 (
line BLOB, line BLOB,
kind ENUM('po', 'pp', 'rr', 'dr', 'rd', 'ts', 'cl') NOT NULL DEFAULT 'po', 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 Table Op Msg_type Msg_text
test.t1 check status OK test.t1 check status OK
drop table t1; 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;

View File

@@ -1,5 +1,10 @@
--source include/have_maria.inc --source include/have_maria.inc
# Initialise
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
# Test for BUG#36319 # Test for BUG#36319
# "Maria: table is not empty but DELETE and SELECT find no rows" # "Maria: table is not empty but DELETE and SELECT find no rows"
@@ -64,3 +69,19 @@ select count(*) from t1;
select name from t1; select name from t1;
check table t1 extended; check table t1 extended;
drop table t1; 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;

View File

@@ -27,7 +27,7 @@
pthread allocate_tls memory loss pthread allocate_tls memory loss
Memcheck:Leak Memcheck:Leak
fun:calloc fun:calloc
obj:/lib64/ld*.so obj:/lib*/ld*.so
fun:_dl_allocate_tls fun:_dl_allocate_tls
fun:pthread_create* 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 Memcheck:Leak
fun:*alloc fun:*alloc
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/libc-*.so obj:/lib*/libc-*.so
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/libc-*.so obj:/lib*/libc-*.so
fun:__libc_dlopen_mode fun:__libc_dlopen_mode
fun:pthread_cancel_init fun:pthread_cancel_init
fun:_Unwind_ForcedUnwind 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 Memcheck:Leak
fun:*alloc fun:*alloc
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/libc-*.so obj:/lib*/libc-*.so
obj:/lib64/ld-*.so obj:/lib*/ld-*.so
obj:/lib64/libc-*.so obj:/lib*/libc-*.so
fun:__libc_dlopen_mode fun:__libc_dlopen_mode
fun:pthread_cancel_init fun:pthread_cancel_init
fun:_Unwind_ForcedUnwind 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 # These seem to be libc threading stuff, not related to MySQL code (allocations

View File

@@ -322,6 +322,13 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
if (share->kfile.file >= 0) if (share->kfile.file >= 0)
_ma_decrement_open_count(info); _ma_decrement_open_count(info);
pthread_mutex_lock(&share->intern_lock); 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; type= do_flush ? FLUSH_RELEASE : FLUSH_IGNORE_CHANGED;
if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX, if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
type, type)) type, type))

View File

@@ -3214,6 +3214,16 @@ void _ma_tmp_disable_logging_for_table(MARIA_HA *info,
/* if we disabled before writing the record, record wouldn't reach log */ /* if we disabled before writing the record, record wouldn't reach log */
share->now_transactional= FALSE; 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 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 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(MARIA_HA *info, my_bool flush_pages)
in not transactional mode in not transactional mode
*/ */
_ma_copy_nontrans_state_information(info); _ma_copy_nontrans_state_information(info);
_ma_reset_history(info->s);
if (flush_pages) if (flush_pages)
{ {

View File

@@ -371,7 +371,7 @@ my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit,
MARIA_STATE_HISTORY *history; MARIA_STATE_HISTORY *history;
pthread_mutex_lock(&share->intern_lock); pthread_mutex_lock(&share->intern_lock);
if (active_transactions && if (active_transactions && share->now_transactional &&
trnman_exists_active_transactions(share->state_history->trid, trnman_exists_active_transactions(share->state_history->trid,
trn->commit_trid, 1)) trn->commit_trid, 1))
{ {
@@ -415,6 +415,35 @@ my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit,
} }
/**
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 The following functions are called by thr_lock() in threaded applications
for transactional tables. for transactional tables.
@@ -509,6 +538,23 @@ void _ma_copy_nontrans_state_information(MARIA_HA *info)
} }
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 Virtual functions to check if row is visible
****************************************************************************/ ****************************************************************************/

View File

@@ -77,3 +77,5 @@ my_bool _ma_row_visible_always(MARIA_HA *info);
my_bool _ma_row_visible_non_transactional_table(MARIA_HA *info); my_bool _ma_row_visible_non_transactional_table(MARIA_HA *info);
my_bool _ma_row_visible_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_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);