Hi Daogang,
Apparently there is no problem with your patch.
However, I prefer a different approach that will help us in the future to simply the "if"
in binlog_rollback. Besides the approach is less risky.
Add a flag to trx_cache in order to track if a non-transactional change was written
to it. Something like set_changes_to_non_trans_temp_table();
If you want we can discuss this tomorrow.
Cheers.
On 09/27/2010 05:04 AM, Dao-Gang.Qu@stripped wrote:
> #At file:///home/daogangqu/mysql/bzrwork1/bug55869/mysql-next-mr-bugfixing/ based on
> revid:mats.kindahl@stripped
>
> 3299 Dao-Gang.Qu@stripped 2010-09-27
> Bug #55869 In mixed mode, the Table_map_event is binloged without any
> rows_log_event.
>
> In mixed mode, the Table_map_event is binlogged without any rows_log_event
> when a unsafe single statement transaction corrupted. It's a wrong behavior.
> The reason is that the Table_map_event will be binlogged with the "ROLLBACK"
> Query_log_event together for a unsafe single stmt transaction, which has
> updated non-transactional table regardless of corruption.
>
> To fix the problem to not binlog the Table_map_event and "ROLLBACK"
> Query_log_event for a unsafe corrupted single stmt transaction,
> although it has updated non-transactional table.
> @ mysql-test/suite/binlog/r/binlog_trans_log.result
> Test result for Bug #55869.
> @ mysql-test/suite/binlog/t/binlog_trans_log.test
> Added the test to verify if Table_map_event is binlogged without
> any rows_log_event for a unsafe corrupted single stmt transaction,
> although it has updated non-transactional table.
>
> added:
> mysql-test/suite/binlog/r/binlog_trans_log.result
> mysql-test/suite/binlog/t/binlog_trans_log.test
> modified:
> sql/binlog.cc
> === added file 'mysql-test/suite/binlog/r/binlog_trans_log.result'
> --- a/mysql-test/suite/binlog/r/binlog_trans_log.result 1970-01-01 00:00:00 +0000
> +++ b/mysql-test/suite/binlog/r/binlog_trans_log.result 2010-09-27 04:04:43 +0000
> @@ -0,0 +1,26 @@
> +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM|
> +CREATE TABLE t2 (a int NOT NULL auto_increment, b int, PRIMARY KEY (a))
> ENGINE=InnoDB|
> +insert into t2 values (1,3)|
> +create function func()
> +RETURNS int(11)
> +DETERMINISTIC
> +begin
> +insert into t1 values (null);
> +select count(*) from t1 into @a;
> +return @a;
> +end|
> +reset master|
> +insert into t2 values (func(),1)|
> +ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
> +# The following must show there are events after the query
> +show binlog events from<binlog_start>|
> +Log_name Pos Event_type Server_id End_log_pos Info
> +master-bin.000001 # Query # # BEGIN
> +master-bin.000001 # Table_map # # table_id: # (test.t1)
> +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
> +master-bin.000001 # Query # # COMMIT
> +select count(*),@a from t1 /* must be 1,1 */|
> +count(*) @a
> +1 1
> +drop table t1,t2;
> +drop function func;
>
> === added file 'mysql-test/suite/binlog/t/binlog_trans_log.test'
> --- a/mysql-test/suite/binlog/t/binlog_trans_log.test 1970-01-01 00:00:00 +0000
> +++ b/mysql-test/suite/binlog/t/binlog_trans_log.test 2010-09-27 04:04:43 +0000
> @@ -0,0 +1,41 @@
> +#
> +# Bug #55869
> +# This test verifies if Table_map_event is binlogged without any
> +# rows_log_event for a unsafe corrupted single stmt transaction,
> +# although it has updated non-transactional table.
> +#
> +
> +--source include/have_innodb.inc
> +--source include/have_binlog_format_mixed.inc
> +
> +delimiter |;
> +
> +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM|
> +CREATE TABLE t2 (a int NOT NULL auto_increment, b int, PRIMARY KEY (a))
> ENGINE=InnoDB|
> +
> +insert into t2 values (1,3)|
> +
> +create function func()
> +RETURNS int(11)
> +DETERMINISTIC
> +begin
> + insert into t1 values (null);
> + select count(*) from t1 into @a;
> + return @a;
> +end|
> +
> +reset master|
> +
> +--error ER_DUP_ENTRY
> +insert into t2 values (func(),1)|
> +
> +--echo # The following must show there are events after the query
> +--source include/show_binlog_events.inc
> +
> +select count(*),@a from t1 /* must be 1,1 */|
> +delimiter ;|
> +
> +# clean-up
> +drop table t1,t2;
> +drop function func;
> +
>
> === modified file 'sql/binlog.cc'
> --- a/sql/binlog.cc 2010-09-17 13:22:22 +0000
> +++ b/sql/binlog.cc 2010-09-27 04:04:43 +0000
> @@ -665,7 +665,8 @@ static int binlog_rollback(handlerton *h
> thd->variables.binlog_format == BINLOG_FORMAT_MIXED) ||
> (trans_has_updated_non_trans_table(thd)&&
> ending_single_stmt_trans(thd,all)&&
> - thd->variables.binlog_format == BINLOG_FORMAT_MIXED)))
> + thd->variables.binlog_format == BINLOG_FORMAT_MIXED
> +&& !(thd->is_error()&& thd->lex->is_stmt_unsafe()))))
> {
> Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE, TRUE, 0);
> error= binlog_flush_trx_cache(thd, cache_mngr,&qev);
>
>
>
>
>