From 9b11bc02ae792d5154efd08852e0120690c323e8 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Wed, 4 Feb 2009 12:13:54 +0200 Subject: Bug #41183 rpl_ndb_circular, rpl_ndb_circular_simplex need maintenance, crash The bug happened because filtering-out a STMT_END_F-flagged event so that the transaction COMMIT finds traces of incomplete statement commit. Such situation is only possible with ndb circular replication. The filtered-out rows event is one that immediately preceeds the COMMIT query event. Fixed with deploying an the rows-log-event statement commit at executing of the transaction COMMIT event. Resources that were allocated by other than STMT_END_F-flagged event of the last statement are clean up prior execution of the commit logics. mysql-test/suite/rpl_ndb/t/disabled.def: re-enabling two tests. sql/log_event.cc: Adding the statement cleanup to execute at the transaction commit time. The statement might not be ended with execution of STMT_END_F-flagged event because of the event was filtered out by SERVER_ID rules. Small refactoring for Rows_log_event::do_update_pos() to be split on two parts: the statement commit that releases its execution time allocated resources, and the relay log update. --- mysql-test/suite/rpl_ndb/t/disabled.def | 3 -- sql/log_event.cc | 88 ++++++++++++++++++++++++++++----- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/rpl_ndb/t/disabled.def b/mysql-test/suite/rpl_ndb/t/disabled.def index 694f7098980..6908269d014 100644 --- a/mysql-test/suite/rpl_ndb/t/disabled.def +++ b/mysql-test/suite/rpl_ndb/t/disabled.def @@ -10,7 +10,4 @@ # ############################################################################## -rpl_ndb_circular : Bug#41183 rpl_ndb_circular, rpl_ndb_circular_simplex need maintenance, crash -rpl_ndb_circular_simplex : Bug#41183 rpl_ndb_circular, rpl_ndb_circular_simplex need maintenance, crash - # the below testcase have been reworked to avoid the bug, test contains comment, keep bug open diff --git a/sql/log_event.cc b/sql/log_event.cc index 0f980f1808d..850b03589a1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -51,6 +51,7 @@ */ #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1) +static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd); #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) static const char *HA_ERR(int i) @@ -2894,7 +2895,37 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos)); clear_all_errors(thd, const_cast(rli)); - const_cast(rli)->clear_tables_to_lock(); + if (strcmp("COMMIT", query) == 0 && rli->tables_to_lock) + { + /* + Cleaning-up the last statement context: + the terminal event of the current statement flagged with + STMT_END_F got filtered out in ndb circular replication. + */ + int error; + char llbuff[22]; + if ((error= rows_event_stmt_cleanup(const_cast(rli), thd))) + { + const_cast(rli)->report(ERROR_LEVEL, error, + "Error in cleaning up after an event preceeding the commit; " + "the group log file/position: %s %s", + const_cast(rli)->group_master_log_name, + llstr(const_cast(rli)->group_master_log_pos, + llbuff)); + } + /* + Executing a part of rli->stmt_done() logics that does not deal + with group position change. The part is redundant now but is + future-change-proof addon, e.g if COMMIT handling will start checking + invariants like IN_STMT flag must be off at committing the transaction. + */ + const_cast(rli)->inc_event_relay_log_pos(); + const_cast(rli)->clear_flag(Relay_log_info::IN_STMT); + } + else + { + const_cast(rli)->clear_tables_to_lock(); + } /* Note: We do not need to execute reset_one_shot_variables() if this @@ -7403,16 +7434,20 @@ Rows_log_event::do_shall_skip(Relay_log_info *rli) return Log_event::do_shall_skip(rli); } -int -Rows_log_event::do_update_pos(Relay_log_info *rli) -{ - DBUG_ENTER("Rows_log_event::do_update_pos"); - int error= 0; - - DBUG_PRINT("info", ("flags: %s", - get_flags(STMT_END_F) ? "STMT_END_F " : "")); +/** + The function is called at Rows_log_event statement commit time, + normally from Rows_log_event::do_update_pos() and possibly from + Query_log_event::do_apply_event() of the COMMIT. + The function commits the last statement for engines, binlog and + releases resources have been allocated for the statement. + + @retval 0 Ok. + @retval non-zero Error at the commit. + */ - if (get_flags(STMT_END_F)) +static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd) +{ + int error; { /* This is the end of a statement or transaction, so close (and @@ -7454,14 +7489,39 @@ Rows_log_event::do_update_pos(Relay_log_info *rli) thd->reset_current_stmt_binlog_row_based(); - rli->cleanup_context(thd, 0); - if (error == 0) + const_cast(rli)->cleanup_context(thd, 0); + } + return error; +} + +/** + The method either increments the relay log position or + commits the current statement and increments the master group + possition if the event is STMT_END_F flagged and + the statement corresponds to the autocommit query (i.e replicated + without wrapping in BEGIN/COMMIT) + + @retval 0 Success + @retval non-zero Error in the statement commit + */ +int +Rows_log_event::do_update_pos(Relay_log_info *rli) +{ + DBUG_ENTER("Rows_log_event::do_update_pos"); + int error= 0; + + DBUG_PRINT("info", ("flags: %s", + get_flags(STMT_END_F) ? "STMT_END_F " : "")); + + if (get_flags(STMT_END_F)) + { + if ((error= rows_event_stmt_cleanup(rli, thd)) == 0) { /* Indicate that a statement is finished. Step the group log position if we are not in a transaction, otherwise increase the event log position. - */ + */ rli->stmt_done(log_pos, when); /* @@ -7475,11 +7535,13 @@ Rows_log_event::do_update_pos(Relay_log_info *rli) thd->clear_error(); } else + { rli->report(ERROR_LEVEL, error, "Error in %s event: commit of row events failed, " "table `%s`.`%s`", get_type_str(), m_table->s->db.str, m_table->s->table_name.str); + } } else { -- cgit v1.2.1 From 5aef51b5d31d405488d7cda8e8001f4ac201fa19 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Wed, 4 Feb 2009 13:08:27 +0200 Subject: Bug #41183 rpl_ndb_circular, rpl_ndb_circular_simplex need maintenance, crash fixing build issue, caused by the previous push. sql/log_event.cc: moving a new declaration out of mysqlbinlog compilation scope. --- sql/log_event.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 850b03589a1..0e400ac2705 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -51,9 +51,10 @@ */ #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1) -static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd); #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) +static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd); + static const char *HA_ERR(int i) { switch (i) { -- cgit v1.2.1