Commit d3d7c46b authored by ingo@mysql.com's avatar ingo@mysql.com

Bug#8306 - TRUNCATE leads to index corruption

Added a check, if the table, which we are going to create, is open.
This can happen if a MERGE mapped table is TRUNCATEd.
parent af2999b7
...@@ -533,6 +533,21 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, ...@@ -533,6 +533,21 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
create_flag=MY_DELETE_OLD; create_flag=MY_DELETE_OLD;
} }
/*
If a MRG_MyISAM table is in use, the mapped MyISAM tables are open,
but no entry is made in the table cache for them.
A TRUNCATE command checks for the table in the cache only and could
be fooled to believe, the table is not open.
Pull the emergency brake in this situation. (Bug #8306)
*/
if (test_if_reopen(filename))
{
my_printf_error(0, "MyISAM table '%s' is in use "
"(most likely by a MERGE table). Try FLUSH TABLES.",
MYF(0), name + dirname_length(name));
goto err;
}
if ((file= my_create_with_symlink(linkname_ptr, if ((file= my_create_with_symlink(linkname_ptr,
filename, filename,
0, O_RDWR | O_TRUNC, 0, O_RDWR | O_TRUNC,
......
...@@ -50,7 +50,7 @@ if (pos > end_pos) \ ...@@ -50,7 +50,7 @@ if (pos > end_pos) \
** In MySQL the server will handle version issues. ** In MySQL the server will handle version issues.
******************************************************************************/ ******************************************************************************/
static MI_INFO *test_if_reopen(char *filename) MI_INFO *test_if_reopen(char *filename)
{ {
LIST *pos; LIST *pos;
......
...@@ -705,6 +705,7 @@ void mi_copy_status(void* to,void *from); ...@@ -705,6 +705,7 @@ void mi_copy_status(void* to,void *from);
my_bool mi_check_status(void* param); my_bool mi_check_status(void* param);
void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
extern MI_INFO *test_if_reopen(char *filename);
my_bool check_table_is_closed(const char *name, const char *where); my_bool check_table_is_closed(const char *name, const char *where);
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup); int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup);
int mi_open_keyfile(MYISAM_SHARE *share); int mi_open_keyfile(MYISAM_SHARE *share);
......
...@@ -555,3 +555,21 @@ select count(*) from t1 where a is null; ...@@ -555,3 +555,21 @@ select count(*) from t1 where a is null;
count(*) count(*)
2 2
drop table t1; drop table t1;
create table t1 (c1 int, index(c1));
create table t2 (c1 int, index(c1)) engine=merge union=(t1);
insert into t1 values (1);
flush tables;
select * from t2;
c1
1
flush tables;
truncate table t1;
insert into t1 values (1);
flush tables;
select * from t2;
c1
1
truncate table t1;
ERROR HY000: MyISAM table 't1' is in use (most likely by a MERGE table). Try FLUSH TABLES.
insert into t1 values (1);
drop table t1,t2;
...@@ -524,3 +524,29 @@ explain select count(*) from t1 where a is null; ...@@ -524,3 +524,29 @@ explain select count(*) from t1 where a is null;
select count(*) from t1 where a is null; select count(*) from t1 where a is null;
drop table t1; drop table t1;
#
# Bug #8306: TRUNCATE leads to index corruption
#
create table t1 (c1 int, index(c1));
create table t2 (c1 int, index(c1)) engine=merge union=(t1);
insert into t1 values (1);
# Close all tables.
flush tables;
# Open t2 and (implicitly) t1.
select * from t2;
# Truncate after flush works (unless another threads reopens t2 in between).
flush tables;
truncate table t1;
insert into t1 values (1);
# Close all tables.
flush tables;
# Open t2 and (implicitly) t1.
select * from t2;
# Truncate t1, wich was not recognized as open without the bugfix.
# Now, it should fail with a table-in-use error message.
--error 1105
truncate table t1;
# The insert used to fail on the crashed table.
insert into t1 values (1);
drop table t1,t2;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment