diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-07-28 10:33:26 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-07-28 10:33:26 +0300 |
commit | f79cebb4d02a7b5151ac617bc762c3e094436562 (patch) | |
tree | 16008fa4f8d8d0b9b884670f6d850ae6a151520a /sql/log.cc | |
parent | 1630037959ab9516fc2a56d4901d2e5d794bc8e7 (diff) | |
parent | 742e1c727fc2be50b758068c2ab92abb19f3ff56 (diff) | |
download | mariadb-git-f79cebb4d02a7b5151ac617bc762c3e094436562.tar.gz |
Merge 10.7 into 10.8
Diffstat (limited to 'sql/log.cc')
-rw-r--r-- | sql/log.cc | 78 |
1 files changed, 57 insertions, 21 deletions
diff --git a/sql/log.cc b/sql/log.cc index 115b1301108..89603448ccd 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2363,7 +2363,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) error |= binlog_commit_flush_stmt_cache(thd, all, cache_mngr); } - if (cache_mngr->trx_cache.empty() && + if (!cache_mngr->trx_cache.has_incident() && cache_mngr->trx_cache.empty() && thd->transaction->xid_state.get_state_code() != XA_PREPARED) { /* @@ -6086,7 +6086,6 @@ void THD::binlog_prepare_for_row_logging() bool THD::binlog_write_annotated_row(Log_event_writer *writer) { - int error; DBUG_ENTER("THD::binlog_write_annotated_row"); if (!(IF_WSREP(!wsrep_fragments_certified_for_stmt(this), true) && @@ -6095,13 +6094,7 @@ bool THD::binlog_write_annotated_row(Log_event_writer *writer) DBUG_RETURN(0); Annotate_rows_log_event anno(this, 0, false); - if (unlikely((error= writer->write(&anno)))) - { - if (my_errno == EFBIG) - writer->set_incident(); - DBUG_RETURN(error); - } - DBUG_RETURN(0); + DBUG_RETURN(writer->write(&anno)); } @@ -6174,21 +6167,22 @@ bool THD::binlog_write_table_maps() /** - This function writes a table map to the binary log. - Note that in order to keep the signature uniform with related methods, - we use a redundant parameter to indicate whether a transactional table - was changed or not. + This function writes a table map to the binary log. - @param table a pointer to the table. - @param with_annotate If true call binlog_write_annotated_row() + If an error occurs while writing events and rollback is not possible, e.g. + due to the statement modifying a non-transactional table, an incident event + is logged. + @param table a pointer to the table. + @param with_annotate @c true to write an annotate event before writing + the table_map event, @c false otherwise. @return nonzero if an error pops up when writing the table map event. */ bool THD::binlog_write_table_map(TABLE *table, bool with_annotate) { - int error; + int error= 1; bool is_transactional= table->file->row_logging_has_trans; DBUG_ENTER("THD::binlog_write_table_map"); DBUG_PRINT("enter", ("table: %p (%s: #%lu)", @@ -6214,12 +6208,34 @@ bool THD::binlog_write_table_map(TABLE *table, bool with_annotate) if (with_annotate) if (binlog_write_annotated_row(&writer)) - DBUG_RETURN(1); + goto write_err; + + DBUG_EXECUTE_IF("table_map_write_error", + { + if (is_transactional) + { + my_errno= EFBIG; + goto write_err; + } + }); if (unlikely((error= writer.write(&the_event)))) - DBUG_RETURN(error); + goto write_err; DBUG_RETURN(0); + +write_err: + mysql_bin_log.set_write_error(this, is_transactional); + /* + For non-transactional engine or multi statement transaction with mixed + engines, data is written to table but writing to binary log failed. In + these scenarios rollback is not possible. Hence report an incident. + */ + if (mysql_bin_log.check_write_error(this) && cache_data && + lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) && + table->current_lock == F_WRLCK) + cache_data->set_incident(); + DBUG_RETURN(error); } @@ -6622,11 +6638,13 @@ MYSQL_BIN_LOG::bump_seq_no_counter_if_needed(uint32 domain_id, uint64 seq_no) bool MYSQL_BIN_LOG::check_strict_gtid_sequence(uint32 domain_id, uint32 server_id_arg, - uint64 seq_no) + uint64 seq_no, + bool no_error) { return rpl_global_gtid_binlog_state.check_strict_sequence(domain_id, server_id_arg, - seq_no); + seq_no, + no_error); } @@ -7655,7 +7673,9 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd) if (likely(is_open())) { prev_binlog_id= current_binlog_id; - if (likely(!(error= write_incident_already_locked(thd))) && + if (likely(!(error= DBUG_IF("incident_event_write_error") + ? 1 + : write_incident_already_locked(thd))) && likely(!(error= flush_and_sync(0)))) { update_binlog_end_pos(); @@ -7684,6 +7704,22 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd) mysql_mutex_unlock(&LOCK_log); } + /* + Upon writing incident event, check for thd->error() and print the + relevant error message in the error log. + */ + if (thd->is_error()) + { + sql_print_error("Write to binary log failed: " + "%s. An incident event is written to binary log " + "and slave will be stopped.\n", + thd->get_stmt_da()->message()); + } + if (error) + { + sql_print_error("Incident event write to the binary log file failed."); + } + DBUG_RETURN(error); } |