diff options
author | Konstantin Osipov <kostja@sun.com> | 2009-12-08 16:57:25 +0300 |
---|---|---|
committer | Konstantin Osipov <kostja@sun.com> | 2009-12-08 16:57:25 +0300 |
commit | 463dcbb51ccea25b07e7b6d0d3787120c4fa895d (patch) | |
tree | 793d0dad1581ef83133f9fc62cb89d7823dea4a3 /mysql-test/r/merge_recover.result | |
parent | ce5c87a3d359d528111d84b5c75bdb8acfe3fb9c (diff) | |
download | mariadb-git-463dcbb51ccea25b07e7b6d0d3787120c4fa895d.tar.gz |
Backport of revid 2617.69.21, 2617.69.22, 2617.29.23:
----------------------------------------------------------
revno: 2617.69.21
committer: Konstantin Osipov <kostja@sun.com>
branch nick: 5.4-4284-1-assert
timestamp: Thu 2009-08-13 20:13:55 +0400
message:
A fix and a test case for Bug#46610 "MySQL 5.4.4: MyISAM MRG engine crash
on auto-repair of child".
Also fixes Bug#42862 "Crash on failed attempt to open a children of a
merge table".
MERGE engine needs to extend the global table list
with TABLE_LIST elements for child tables,
so that they are opened and locked.
Previously these table list elements were allocated
in memory of ha_myisammrg object (MERGE engine handler).
That would lead to access to freed memory in
recover_from_failed_open_table_attempt(), which would
try to recover a MERGE table child (MyISAM table)
and use for that TABLE_LIST of that child.
But by the time recover_from_failed_open_table_attempt()
is invoked, ha_myisammrg object that owns this
TABLE_LIST may be destroyed, and thus TABLE_LIST
memory freed.
The fix is to ensure that TABLE_LIST elements
that are added to the global table list (lex->query_tables)
are always allocated in thd->mem_root, which is not
destroyed until end of execution.
If previously TABLE_LIST elements were allocated
at ha_myisammrg::open() (i.e. when the TABLE
object was created and added to the table cache),
now they are allocated in ha_myisammrg::add_chidlren_list()
(i.e. right after "open" of the merge parent in
open_tables()).
We still create a list of children names
at ha_myisammrg::open() to use as a basis
for creation of TABLE_LISTs, that allows
to avoid reading the merge handler data
file on every execution.
mysql-test/r/merge_recover.result:
Test results for Bug#46610.
mysql-test/t/merge_recover-master.opt:
Option file for Bug#46610 test (need a new test because
of that option, which is not tested anywhere else).
mysql-test/t/merge_recover.test:
Add a test case for Bug#46610.
sql/table.h:
MERGE child child_def_version is now moved from TABLE_LIST
to MERGE engine specific data structure.
storage/myisammrg/ha_myisammrg.cc:
Introduce an auxiliary structure to keep MERGE child name
and definition version. A list of Mrg_child_def is created
in ha_myisammrg::open() and reused in ha_myisammrg::add_children_list().
Diffstat (limited to 'mysql-test/r/merge_recover.result')
-rw-r--r-- | mysql-test/r/merge_recover.result | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/mysql-test/r/merge_recover.result b/mysql-test/r/merge_recover.result new file mode 100644 index 00000000000..871c12ca4c0 --- /dev/null +++ b/mysql-test/r/merge_recover.result @@ -0,0 +1,103 @@ +# +# Test of MyISAM MRG tables with corrupted children. +# Run with --myisam-recover=force option. +# +# Preparation: we need to make sure that the merge parent +# is never left in the table cache when closed, since this may +# have effect on merge children. +# For that, we set the table cache to minimal size and populate it +# in a concurrent connection. +# +# Switching to connection con1 +# +# +# Minimal values. +# +call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:"); +call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*root Checking table"); +call mtr.add_suppression(" '\..test.t1'"); +set global table_open_cache=256; +set global table_definition_cache=400; +drop procedure if exists p_create; +create procedure p_create() +begin +declare i int default 1; +set @lock_table_stmt="lock table "; +set @drop_table_stmt="drop table "; +while i < @@global.table_definition_cache + 1 do +set @table_name=concat("t_", i); +set @opt_comma=if(i=1, "", ", "); +set @lock_table_stmt=concat(@lock_table_stmt, @opt_comma, +@table_name, " read"); +set @drop_table_stmt=concat(@drop_table_stmt, @opt_comma, @table_name); +set @create_table_stmt=concat("create table if not exists ", +@table_name, " (a int)"); +prepare stmt from @create_table_stmt; +execute stmt; +deallocate prepare stmt; +set i= i+1; +end while; +end| +call p_create(); +drop procedure p_create; +# +# Switching to connection 'default' +# +# +# We have to disable the ps-protocol, to avoid +# "Prepared statement needs to be re-prepared" errors +# -- table def versions change all the time with full table cache. +# +drop table if exists t1, t1_mrg, t1_copy; +# +# Prepare a MERGE engine table, that refers to a corrupted +# child. +# +create table t1 (a int, key(a)) engine=myisam; +create table t1_mrg (a int) union (t1) engine=merge; +# +# Create a table with a corrupted index file: +# save an old index file, insert more rows, +# overwrite the new index file with the old one. +# +insert into t1 (a) values (1), (2), (3); +flush table t1; +insert into t1 (a) values (4), (5), (6); +flush table t1; +# check table is needed to mark the table as crashed. +check table t1; +Table Op Msg_type Msg_text +test.t1 check warning Size of datafile is: 42 Should be: 21 +test.t1 check error Record-count is not ok; is 6 Should be: 3 +test.t1 check warning Found 6 key parts. Should be: 3 +test.t1 check error Corrupt +# +# At this point we have a merge table t1_mrg pointing to t1, +# and t1 is corrupted, and will be auto-repaired at open. +# Check that this doesn't lead to memory corruption. +# +select * from t1_mrg; +a +1 +2 +3 +4 +5 +6 +Warnings: +Error 145 Table 't1' is marked as crashed and should be repaired +Error 1194 Table 't1' is marked as crashed and should be repaired +Error 1034 Number of rows changed from 3 to 6 +# +# Cleanup +# +drop table t1, t1_mrg; +# +# Switching to connection con1 +# +unlock tables; +prepare stmt from @drop_table_stmt; +execute stmt; +deallocate prepare stmt; +set @@global.table_definition_cache=default; +set @@global.table_open_cache=default; |