summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <Li-Bing.Song@sun.com>2010-10-11 11:08:49 +0800
committerunknown <Li-Bing.Song@sun.com>2010-10-11 11:08:49 +0800
commit42f8d2f249ea4d0acc2fdd7c03b3ea9d44f92027 (patch)
treeb95862a484aecf45c73ba883241975c8b52e2c4b
parenteec585f143613679692a71795e840efb5bbfbe0b (diff)
downloadmariadb-git-42f8d2f249ea4d0acc2fdd7c03b3ea9d44f92027.tar.gz
Bug#56226 Table map set to 0 after altering MyISAM table
After ALTER TABLE which changed only table's metadata, row-based binlog sometimes got corrupted since the tablemap was unexpectedly set to 0 for subsequent updates to the same table. ALTER TABLE which changed only table's metadata always reset table_map_id for the table share to 0. Despite the fact that 0 is a valid value for table_map_id, this step caused problems as it could have created situation in which we had more than one table share with table_map_id equal 0. If more than one table with table_map_id are 0 were updated in the same statement, updates to these different tables were written into the same rows event. This caused slave server to crash. This bug happens only on 5.1. It doesn't affect 5.5+. This patch solves this problem by ensuring that ALTER TABLE statements which change metadata only never reset table_map_id to 0. To do this it changes reopen_table() to correctly use refreshed table_map_id value instead of using the old one/ resetting it. 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
-rw-r--r--mysql-test/suite/rpl/r/rpl_alter.result20
-rw-r--r--mysql-test/suite/rpl/t/rpl_alter.test59
-rw-r--r--sql/sql_base.cc2
3 files changed, 73 insertions, 8 deletions
diff --git a/mysql-test/suite/rpl/r/rpl_alter.result b/mysql-test/suite/rpl/r/rpl_alter.result
index 6ef5ce3462a..cedb6854239 100644
--- a/mysql-test/suite/rpl/r/rpl_alter.result
+++ b/mysql-test/suite/rpl/r/rpl_alter.result
@@ -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;
diff --git a/mysql-test/suite/rpl/t/rpl_alter.test b/mysql-test/suite/rpl/t/rpl_alter.test
index 576376a0264..bc42476244a 100644
--- a/mysql-test/suite/rpl/t/rpl_alter.test
+++ b/mysql-test/suite/rpl/t/rpl_alter.test
@@ -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
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index c38526a6d0b..3766ff18293 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3082,8 +3082,6 @@ 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;
-
/* Get state */
tmp.in_use= thd;
tmp.reginfo.lock_type=table->reginfo.lock_type;