#At file:///home/anders/work/bzrroot/mysql-5.1-rep-semisync/ based on revid:zhenxing.he@stripped
3127 Li-Bing.Song@stripped 2010-01-20
BUG#50157 Assertion !active_tranxs_->is_tranx_end_pos(..) in ReplSemiSyncMaster::commitTrx
The root cause of the crash is that a TranxNode is freed before it is used.
A TranxNode is created when each time some log events are written into binlog file
and is synchronized. TranxNodes' memories are allocted from mem_root of the current
thread, and will be freed immediately after current statement ending.
Sometimes, a statement ends and its TranxNode is freed before it is cleared
from TranxNode list. So the Pointer of the TranxNode in TranxNode list becomes a
wild pointer.
After this patch, One statement always waits until its log events has been replicated
completely if it has been binlogged and synchronized. For the TranxNode will be
cleared from the TranxNode list after the log event has been replicated.
@ sql/rpl_handler.cc
params are not initialized.
added:
mysql-test/suite/rpl/r/rpl_semi_sync_mixed_tables.result
mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables-master.opt
mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables-slave.opt
mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables.test
modified:
plugin/semisync/semisync_master_plugin.cc
sql/rpl_handler.cc
=== added file 'mysql-test/suite/rpl/r/rpl_semi_sync_mixed_tables.result'
--- a/mysql-test/suite/rpl/r/rpl_semi_sync_mixed_tables.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_semi_sync_mixed_tables.result 2010-01-20 08:37:18 +0000
@@ -0,0 +1,36 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+
+##############################################################################
+# BUG#50157
+# semi-sync replication crashes when 'CREATE TEMPORARY TABLE `MyISAM_t` SELECT
+# * FROM `Innodb_t`;
+##############################################################################
+SET AUTOCOMMIT= 0;
+CREATE TABLE t2(c1 INT) ENGINE=innodb;
+call mtr.add_suppression(".*");
+INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
+SET GLOBAL rpl_semi_sync_master_enabled = 1;
+SET GLOBAL rpl_semi_sync_master_trace_level= 80;
+STOP SLAVE;
+INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
+SET GLOBAL rpl_semi_sync_slave_enabled = 1;
+START SLAVE;
+BEGIN;
+
+# Even though it is in a transaction, this statement is binlogged into binlog
+# file immediately.
+CREATE TEMPORARY TABLE t1 LIKE t2;
+
+# These statements will not binlogged until the transaction is committed
+INSERT INTO t2 VALUES(11);
+INSERT INTO t2 VALUES(22);
+COMMIT;
+
+UNINSTALL PLUGIN rpl_semi_sync_slave;
+UNINSTALL PLUGIN rpl_semi_sync_master;
+DROP TABLE t1, t2;
=== added file 'mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables-master.opt'
--- a/mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables-master.opt 2010-01-20 08:37:18 +0000
@@ -0,0 +1 @@
+$SEMISYNC_PLUGIN_OPT
=== added file 'mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables-slave.opt'
--- a/mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables-slave.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables-slave.opt 2010-01-20 08:37:18 +0000
@@ -0,0 +1 @@
+$SEMISYNC_PLUGIN_OPT
=== added file 'mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables.test'
--- a/mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables.test 2010-01-20 08:37:18 +0000
@@ -0,0 +1,53 @@
+source include/have_semisync_plugin.inc;
+source include/not_embedded.inc;
+source include/have_innodb.inc;
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+--echo
+--echo ##############################################################################
+--echo # BUG#50157
+--echo # semi-sync replication crashes when 'CREATE TEMPORARY TABLE `MyISAM_t` SELECT
+--echo # * FROM `Innodb_t`;
+--echo ##############################################################################
+
+SET AUTOCOMMIT= 0;
+CREATE TABLE t2(c1 INT) ENGINE=innodb;
+sync_slave_with_master;
+
+connection master;
+call mtr.add_suppression(".*");
+eval INSTALL PLUGIN rpl_semi_sync_master SONAME '$SEMISYNC_MASTER_PLUGIN';
+SET GLOBAL rpl_semi_sync_master_enabled = 1;
+SET GLOBAL rpl_semi_sync_master_trace_level= 80;
+
+connection slave;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+
+eval INSTALL PLUGIN rpl_semi_sync_slave SONAME '$SEMISYNC_SLAVE_PLUGIN';
+SET GLOBAL rpl_semi_sync_slave_enabled = 1;
+
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+connection master;
+BEGIN;
+--echo
+--echo # Even though it is in a transaction, this statement is binlogged into binlog
+--echo # file immediately.
+CREATE TEMPORARY TABLE t1 SELECT c1 FROM t2 where 1=1;
+--echo
+--echo # These statements will not binlogged until the transaction is committed
+INSERT INTO t2 VALUES(11);
+INSERT INTO t2 VALUES(22);
+COMMIT;
+sync_slave_with_master;
+
+--echo
+UNINSTALL PLUGIN rpl_semi_sync_slave;
+connection master;
+UNINSTALL PLUGIN rpl_semi_sync_master;
+
+DROP TABLE t1, t2;
+source include/master-slave-end.inc;
=== modified file 'plugin/semisync/semisync_master_plugin.cc'
--- a/plugin/semisync/semisync_master_plugin.cc 2009-10-18 12:29:03 +0000
+++ b/plugin/semisync/semisync_master_plugin.cc 2010-01-20 08:37:18 +0000
@@ -46,10 +46,7 @@ int repl_semi_request_commit(Trans_param
int repl_semi_report_commit(Trans_param *param)
{
-
- bool is_real_trans= param->flags & TRANS_IS_REAL_TRANS;
-
- if (is_real_trans && param->log_pos)
+ if (param->log_pos)
{
const char *binlog_name= param->log_file;
return repl_semisync.commitTrx(binlog_name, param->log_pos);
=== modified file 'sql/rpl_handler.cc'
--- a/sql/rpl_handler.cc 2009-12-04 01:46:33 +0000
+++ b/sql/rpl_handler.cc 2010-01-20 08:37:18 +0000
@@ -190,8 +190,8 @@ int Trans_delegate::after_commit(THD *th
{
Trans_param param;
bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
- if (is_real_trans)
- param.flags |= TRANS_IS_REAL_TRANS;
+
+ param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0;
Trans_binlog_info *log_info=
my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
@@ -218,8 +218,8 @@ int Trans_delegate::after_rollback(THD *
{
Trans_param param;
bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
- if (is_real_trans)
- param.flags |= TRANS_IS_REAL_TRANS;
+
+ param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0;
Trans_binlog_info *log_info=
my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
@@ -228,7 +228,7 @@ int Trans_delegate::after_rollback(THD *
param.log_pos= log_info ? log_info->log_pos : 0;
int ret= 0;
- FOREACH_OBSERVER(ret, after_commit, thd, (¶m));
+ FOREACH_OBSERVER(ret, after_rollback, thd, (¶m));
/*
This is the end of a real transaction or autocommit statement, we
@@ -249,6 +249,7 @@ int Binlog_storage_delegate::after_flush
{
Binlog_storage_param param;
uint32 flags=0;
+
if (synced)
flags |= BINLOG_STORAGE_IS_SYNCED;
Attachment: [text/bzr-bundle] bzr/li-bing.song@sun.com-20100120083718-c0yr5tnjwyq7qcwg.bundle