mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 04:53:01 +01:00
Fix for BUG#16559 "Replication Problems with Non transactional tables inside an interrupted trans.":
problem was: when a connection disconnects having an open transaction affecting MyISAM and InnoDB, the ROLLBACK event stored in the binary log contained a non-zero error code (1053 because of the disconnection), so when slave applied the transaction, slave complained that its ROLLBACK succeeded (error_code=0) while master's had 1053, so slave stopped. But internally generated binlog events such as this ROLLBACK should always have 0 as error code, as is true in 4.1 and was accidentally broken in 5.0, so that there is no false alarm.
This commit is contained in:
parent
cb74e09f46
commit
4c5d18b150
3 changed files with 60 additions and 2 deletions
|
@ -256,3 +256,26 @@ master-bin.000001 1648 Query 1 # use `test`; create table t2 (n int) engine=inno
|
|||
master-bin.000001 1748 Query 1 # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti`
|
||||
do release_lock("lock1");
|
||||
drop table t0,t2;
|
||||
reset master;
|
||||
create table t1 (a int) engine=innodb;
|
||||
create table t2 (a int) engine=myisam;
|
||||
select get_lock("a",10);
|
||||
get_lock("a",10)
|
||||
1
|
||||
begin;
|
||||
insert into t1 values(8);
|
||||
insert into t2 select * from t1;
|
||||
select get_lock("a",10);
|
||||
get_lock("a",10)
|
||||
1
|
||||
select
|
||||
(@a:=load_file("MYSQL_TEST_DIR/var/tmp/mix_innodb_myisam_binlog.output"))
|
||||
is not null;
|
||||
(@a:=load_file("MYSQL_TEST_DIR/var/tmp/mix_innodb_myisam_binlog.output"))
|
||||
is not null
|
||||
1
|
||||
select
|
||||
@a like "%#%error_code=0%ROLLBACK;%ROLLBACK /* added by mysqlbinlog */;%",
|
||||
@a not like "%#%error_code=%error_code=%";
|
||||
@a like "%#%error_code=0%ROLLBACK;%ROLLBACK /* added by mysqlbinlog */;%" @a not like "%#%error_code=%error_code=%"
|
||||
1 1
|
||||
|
|
|
@ -259,5 +259,36 @@ show binlog events from 98;
|
|||
do release_lock("lock1");
|
||||
drop table t0,t2;
|
||||
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
# Test for BUG#16559 (ROLLBACK should always have a zero error code in
|
||||
# binlog). Has to be here and not earlier, as the SELECTs influence
|
||||
# XIDs differently between normal and ps-protocol (and SHOW BINLOG
|
||||
# EVENTS above read XIDs).
|
||||
|
||||
connect (con4,localhost,root,,);
|
||||
connection con3;
|
||||
reset master;
|
||||
create table t1 (a int) engine=innodb;
|
||||
create table t2 (a int) engine=myisam;
|
||||
select get_lock("a",10);
|
||||
begin;
|
||||
insert into t1 values(8);
|
||||
insert into t2 select * from t1;
|
||||
disconnect con3;
|
||||
|
||||
connection con4;
|
||||
select get_lock("a",10); # wait for rollback to finish
|
||||
|
||||
# we check that the error code of the "ROLLBACK" event is 0 and not
|
||||
# ER_SERVER_SHUTDOWN (i.e. disconnection just rolls back transaction
|
||||
# and does not make slave to stop)
|
||||
--exec $MYSQL_BINLOG --start-position=547 $MYSQL_TEST_DIR/var/log/master-bin.000001 > var/tmp/mix_innodb_myisam_binlog.output
|
||||
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
||||
eval select
|
||||
(@a:=load_file("$MYSQL_TEST_DIR/var/tmp/mix_innodb_myisam_binlog.output"))
|
||||
is not null;
|
||||
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
||||
eval select
|
||||
@a like "%#%error_code=0%ROLLBACK;%ROLLBACK /* added by mysqlbinlog */;%",
|
||||
@a not like "%#%error_code=%error_code=%";
|
||||
|
|
|
@ -132,6 +132,7 @@ static int binlog_commit(THD *thd, bool all)
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
|
||||
qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
|
||||
DBUG_RETURN(binlog_end_trans(thd, trans_log, &qev));
|
||||
}
|
||||
|
||||
|
@ -156,6 +157,7 @@ static int binlog_rollback(THD *thd, bool all)
|
|||
if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE))
|
||||
{
|
||||
Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE);
|
||||
qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
|
||||
error= binlog_end_trans(thd, trans_log, &qev);
|
||||
}
|
||||
else
|
||||
|
@ -1826,7 +1828,9 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
|
|||
Imagine this is rollback due to net timeout, after all statements of
|
||||
the transaction succeeded. Then we want a zero-error code in BEGIN.
|
||||
In other words, if there was a really serious error code it's already
|
||||
in the statement's events.
|
||||
in the statement's events, there is no need to put it also in this
|
||||
internally generated event, and as this event is generated late it
|
||||
would lead to false alarms.
|
||||
This is safer than thd->clear_error() against kills at shutdown.
|
||||
*/
|
||||
qinfo.error_code= 0;
|
||||
|
|
Loading…
Reference in a new issue