From 5cbdb908270a052284155cd5b7eff7eacb177218 Mon Sep 17 00:00:00 2001 From: Sujatha Sivakumar Date: Mon, 17 Sep 2012 11:48:02 +0530 Subject: Bug#11750014:ASSERTION TRX_DATA->EMPTY() IN BINLOG_CLOSE_CONNECTION Problem: ======= trx_data->empty() assert happens at `binlog_close_connection' Analysis: ======== trx_data->empty() function checks for no pending events and the transaction cache to be empty.This function returns "true" if no pending events are present and cache is empty. Otherwise it returns false. `binlog_close_connection' call expects the above function to return true. But if the return value is false then assert is raised. This bug was reproducible in a diskfull scenario. In this disk full scenario try to do an insert operation so that a new pending event is created and flushing this pending event fails. Due to this failure the server goes down and invokes `binlog_close_connection' for clean closure. Since the pending event still remains the assert is caused. This assert is caused only in non transactional databases. Fix: === In a disk full scenario when the insertion fails the transaction is rolled back and `binlog_end_trans` is called to flush the pending events. But flush operation fails as the disk is full and the function simply returns `1' without taking any action to delete the pending event. This leaves the event to remain till the closure of connection. `delete pending' statement has been added to do the required clean up action. sql/log.cc: Added "delete pending" statement to clean pending event --- sql/log.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sql/log.cc') diff --git a/sql/log.cc b/sql/log.cc index 57c14b24782..7e0e90e28c0 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4313,10 +4313,16 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, /* Write pending event to log file or transaction cache */ + DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending", + {DBUG_SET("+d,simulate_file_write_error");}); if (pending->write(file)) { pthread_mutex_unlock(&LOCK_log); set_write_error(thd); + delete pending; + trx_data->set_pending(NULL); + DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending", + {DBUG_SET("-d,simulate_file_write_error");}); DBUG_RETURN(1); } -- cgit v1.2.1 From 5530c5e38dbefac8e5d2c333c0f35ed9f73946a4 Mon Sep 17 00:00:00 2001 From: Rohit Kalhans Date: Sat, 22 Sep 2012 17:50:51 +0530 Subject: BUG#14548159: NUMEROUS CASES OF INCORRECT IDENTIFIER QUOTING IN REPLICATION Problem: Misquoting or unquoted identifiers may lead to incorrect statements to be logged to the binary log. Fix: we use specialized functions to append quoted identifiers in the statements generated by the server. --- sql/log.cc | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'sql/log.cc') diff --git a/sql/log.cc b/sql/log.cc index 7e0e90e28c0..93dd70b33c5 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -29,6 +29,7 @@ #include "rpl_filter.h" #include "rpl_rli.h" +#include "sql_show.h" #include #include #include // For test_if_number @@ -1708,17 +1709,24 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) DBUG_ENTER("binlog_savepoint_set"); binlog_trans_log_savepos(thd, (my_off_t*) sv); + + // buffer to store quoted identifier + char* buffer= (char *)my_malloc(sizeof("SAVEPOINT ")+ 1 + NAME_LEN * 2 + 2, + MYF(0)); + String log_query(buffer, sizeof(buffer), system_charset_info); + log_query.length(0); + /* Write it to the binary log */ - String log_query; - if (log_query.append(STRING_WITH_LEN("SAVEPOINT ")) || - log_query.append("`") || - log_query.append(thd->lex->ident.str, thd->lex->ident.length) || - log_query.append("`")) + if (log_query.append(STRING_WITH_LEN("SAVEPOINT "))) DBUG_RETURN(1); + else + append_identifier(thd, &log_query, thd->lex->ident.str, + thd->lex->ident.length); int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); Query_log_event qinfo(thd, log_query.c_ptr_safe(), log_query.length(), TRUE, TRUE, errcode); + my_free(buffer, MYF(MY_WME)); DBUG_RETURN(mysql_bin_log.write(&qinfo)); } @@ -1731,18 +1739,23 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) non-transactional table. Otherwise, truncate the binlog cache starting from the SAVEPOINT command. */ - if (unlikely(trans_has_updated_non_trans_table(thd) || + if (unlikely(trans_has_updated_non_trans_table(thd) || (thd->options & OPTION_KEEP_LOG))) { - String log_query; - if (log_query.append(STRING_WITH_LEN("ROLLBACK TO ")) || - log_query.append("`") || - log_query.append(thd->lex->ident.str, thd->lex->ident.length) || - log_query.append("`")) + // buffer to store rollback query with quoted identifier + char* buffer= (char *)my_malloc(12 + 1 + NAME_LEN * 2 + 2, MYF(0)); + String log_query(buffer, sizeof(buffer), system_charset_info); + log_query.length(0); + + if (log_query.append(STRING_WITH_LEN("ROLLBACK TO "))) DBUG_RETURN(1); + else + append_identifier(thd, &log_query, thd->lex->ident.str, + thd->lex->ident.length); int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); Query_log_event qinfo(thd, log_query.c_ptr_safe(), log_query.length(), TRUE, TRUE, errcode); + my_free(buffer, MYF(MY_WME)); DBUG_RETURN(mysql_bin_log.write(&qinfo)); } binlog_trans_log_truncate(thd, *(my_off_t*)sv); -- cgit v1.2.1