Commit 42f8d2f2 authored by unknown's avatar unknown

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
parent eec585f1
......@@ -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;
......@@ -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
......@@ -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;
......
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