summaryrefslogtreecommitdiff
path: root/sql/log.cc
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2022-07-28 10:33:26 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2022-07-28 10:33:26 +0300
commitf79cebb4d02a7b5151ac617bc762c3e094436562 (patch)
tree16008fa4f8d8d0b9b884670f6d850ae6a151520a /sql/log.cc
parent1630037959ab9516fc2a56d4901d2e5d794bc8e7 (diff)
parent742e1c727fc2be50b758068c2ab92abb19f3ff56 (diff)
downloadmariadb-git-f79cebb4d02a7b5151ac617bc762c3e094436562.tar.gz
Merge 10.7 into 10.8
Diffstat (limited to 'sql/log.cc')
-rw-r--r--sql/log.cc78
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);
}