diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-07-27 17:52:37 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-07-27 17:52:37 +0300 |
commit | 30914389fe9ca13cf29470dd033a5cf6997a3931 (patch) | |
tree | fac7ab85411e556db4759a9a2c063ef27b851f87 /sql/log.cc | |
parent | 772e3f61eb2956143bbdb1d85490bd5aad73d43c (diff) | |
parent | 098c0f2634a35e24e9eb0f06d3fba69d0d097657 (diff) | |
download | mariadb-git-30914389fe9ca13cf29470dd033a5cf6997a3931.tar.gz |
Merge 10.5 into 10.6
Diffstat (limited to 'sql/log.cc')
-rw-r--r-- | sql/log.cc | 72 |
1 files changed, 53 insertions, 19 deletions
diff --git a/sql/log.cc b/sql/log.cc index 11dd979715c..15de3f46275 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2238,7 +2238,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) { /* @@ -5929,7 +5929,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) && @@ -5938,13 +5937,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)); } @@ -6017,21 +6010,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)", @@ -6057,12 +6051,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); } @@ -7498,7 +7514,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_EVALUATE_IF("incident_event_write_error", 1, + write_incident_already_locked(thd)))) && likely(!(error= flush_and_sync(0)))) { update_binlog_end_pos(); @@ -7527,6 +7545,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); } |