#At file:///home/anders/work/bzrwork1/wt2/mysql-5.1-bugteam/ based on revid:mattias.jonsson@stripped
3489 Li-Bing.Song@stripped 2010-09-16
Bug#56226 Table map set to 0 after altering MyISAM table
A MyISAM table's table_map_id will always be reset to 0 after altered
only its metadata. 0 is a valid value of table_map_id. But the problem will
cause that more than one tables have the same table_map_id 0. If more than
one tables which's table_map_id are 0 are updated in one statement, the update
of these different tables will be write into only one rows event. It will
cause slave server to crash.
After this patch, table_map_id always be refreshed as a correct value after
altered only its metadata.
@ mysql-test/suite/rpl/r/rpl_alter.result
Add test for BUG#56226
@ mysql-test/suite/rpl/t/rpl_alter.test
Add test for BUG#56226
@ sql/sql_base.cc
The invalid value of table_map_id is ~0UL.
So it should be set to ~0UL but not 0 when a SHARE is initialized
and we don't want to give a valid value.
Because of this, we are able to know if table_map_id is invalid and should
be set a new value when reopenning the table.
modified:
mysql-test/suite/rpl/r/rpl_alter.result
mysql-test/suite/rpl/t/rpl_alter.test
sql/sql_base.cc
=== modified file 'mysql-test/suite/rpl/r/rpl_alter.result'
--- a/mysql-test/suite/rpl/r/rpl_alter.result 2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/rpl/r/rpl_alter.result 2010-09-16 09:35:41 +0000
@@ -19,3 +19,23 @@ select * from mysqltest.t3;
n
45
drop database mysqltest;
+
+# BUG#56226 Table map set to 0 after altering MyISAM table
+
+SET SESSION binlog_format='ROW';
+USE test;
+CREATE TABLE t1 (a INT, b INT) ENGINE MyISAM;
+CREATE TABLE t2 (a VARCHAR(255), b VARCHAR(255)) ENGINE MyISAM;
+CREATE TRIGGER trg_t1ai
+AFTER INSERT ON t1 FOR EACH ROW
+BEGIN
+INSERT INTO t2 (a) VALUES (NEW.a);
+END;//
+ALTER TABLE t1 CHANGE b c INT;
+ALTER TABLE t2 CHANGE b c VARCHAR(255);
+
+INSERT INTO t1 (a) VALUES(2);
+Comparing tables master:test.t1 and slave:test.t1
+Comparing tables master:test.t2 and slave:test.t2
+
+DROP TABLE t1, t2;
=== modified file 'mysql-test/suite/rpl/t/rpl_alter.test'
--- a/mysql-test/suite/rpl/t/rpl_alter.test 2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/rpl/t/rpl_alter.test 2010-09-16 09:35:41 +0000
@@ -10,15 +10,62 @@ insert into mysqltest.t1 values (1,2);
create table mysqltest.t2 (n int);
insert into mysqltest.t2 values (45);
rename table mysqltest.t2 to mysqltest.t3, mysqltest.t1 to mysqltest.t2;
-save_master_pos;
-connection slave;
-sync_with_master;
+
+sync_slave_with_master;
select * from mysqltest.t2;
select * from mysqltest.t3;
+
connection master;
drop database mysqltest;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
+
+--echo
+--echo # BUG#56226 Table map set to 0 after altering MyISAM table
+--echo
+connection master;
+SET SESSION binlog_format='ROW';
+USE test;
+
+CREATE TABLE t1 (a INT, b INT) ENGINE MyISAM;
+CREATE TABLE t2 (a VARCHAR(255), b VARCHAR(255)) ENGINE MyISAM;
+
+--delimiter //
+CREATE TRIGGER trg_t1ai
+ AFTER INSERT ON t1 FOR EACH ROW
+BEGIN
+ INSERT INTO t2 (a) VALUES (NEW.a);
+END;//
+--delimiter ;
+
+ALTER TABLE t1 CHANGE b c INT;
+ALTER TABLE t2 CHANGE b c VARCHAR(255);
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+--echo
+INSERT INTO t1 (a) VALUES(2);
+let _info= query_get_value(SHOW BINLOG EVENTS IN '$binlog_file' FROM $binlog_start, Info, 2);
+# Table map id should not be 0.
+if (`SELECT 'table_id: 0 (test.t1)' = '$_info'`)
+{
+ --echo test.t1's table map id is 0;
+ --die test.t1's table map id is 0;
+}
+let _info= query_get_value(SHOW BINLOG EVENTS IN '$binlog_file' FROM $binlog_start, Info, 3);
+if (`SELECT 'table_id: 0 (test.t2)' = '$_info'`)
+{
+ --echo test.t2's table map id is 0;
+ --die test.t2's table map id is 0;
+}
+
+let diff_table= test.t1;
+source include/rpl_diff_tables.inc;
+let diff_table= test.t2;
+source include/rpl_diff_tables.inc;
+
+--echo
+connection master;
+DROP TABLE t1, t2;
+source include/master-slave-end.inc;
# End of 4.1 tests
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2010-07-20 18:07:36 +0000
+++ b/sql/sql_base.cc 2010-09-16 09:35:41 +0000
@@ -662,6 +662,7 @@ void close_handle_and_leave_table_as_loc
share->set_table_cache_key(key_buff, old_share->table_cache_key.str,
old_share->table_cache_key.length);
share->tmp_table= INTERNAL_TMP_TABLE; // for intern_close_table()
+ share->table_map_id= ~0UL;
}
/*
@@ -3082,7 +3083,8 @@ bool reopen_table(TABLE *table)
tmp.maybe_null= table->maybe_null;
tmp.status= table->status;
- tmp.s->table_map_id= table->s->table_map_id;
+ if (table->s->table_map_id != ~0UL)
+ tmp.s->table_map_id= table->s->table_map_id;
/* Get state */
tmp.in_use= thd;
Attachment: [text/bzr-bundle] bzr/li-bing.song@sun.com-20100916093541-eu0x892s0hy8nd5a.bundle