summaryrefslogtreecommitdiff
path: root/sql/log_event.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/log_event.cc')
-rw-r--r--sql/log_event.cc60
1 files changed, 33 insertions, 27 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 5236a2794cf..8f70282ce79 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -3332,6 +3332,19 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
thd->table_map_for_update= (table_map)table_map_for_update;
thd->set_invoker(&user, &host);
+ /*
+ Flag if we need to rollback the statement transaction on
+ slave if it by chance succeeds.
+ If we expected a non-zero error code and get nothing and,
+ it is a concurrency issue or ignorable issue, effects
+ of the statement should be rolled back.
+ */
+ if (expected_error &&
+ (ignored_error_code(expected_error) ||
+ concurrency_error_code(expected_error)))
+ {
+ thd->variables.option_bits|= OPTION_MASTER_SQL_ERROR;
+ }
/* Execute the query (note that we bypass dispatch_command()) */
Parser_state parser_state;
if (!parser_state.init(thd, thd->query(), thd->query_length()))
@@ -3340,6 +3353,8 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
log_slow_statement(thd);
}
+ thd->variables.option_bits&= ~OPTION_MASTER_SQL_ERROR;
+
/*
Resetting the enable_slow_log thd variable.
@@ -3382,7 +3397,6 @@ START SLAVE; . Query: '%s'", expected_error, thd->query());
general_log_write(thd, COM_QUERY, thd->query(), thd->query_length());
compare_errors:
-
/*
In the slave thread, we may sometimes execute some DROP / * 40005
TEMPORARY * / TABLE that come from parts of binlogs (likely if we
@@ -3430,26 +3444,8 @@ Default database: '%s'. Query: '%s'",
DBUG_PRINT("info",("error ignored"));
clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
thd->killed= THD::NOT_KILLED;
- /*
- When an error is expected and matches the actual error the
- slave does not report any error and by consequence changes
- on transactional tables are not rolled back in the function
- close_thread_tables(). For that reason, we explicitly roll
- them back here.
- */
- if (expected_error && expected_error == actual_error)
- trans_rollback_stmt(thd);
}
/*
- If we expected a non-zero error code and get nothing and, it is a concurrency
- issue or should be ignored.
- */
- else if (expected_error && !actual_error &&
- (concurrency_error_code(expected_error) ||
- ignored_error_code(expected_error)))
- trans_rollback_stmt(thd);
-
- /*
Other cases: mostly we expected no error and get one.
*/
else if (thd->is_slave_error || thd->is_fatal_error)
@@ -3516,7 +3512,6 @@ end:
thd->set_db(NULL, 0); /* will free the current database */
thd->set_query(NULL, 0);
DBUG_PRINT("info", ("end: query= 0"));
- close_thread_tables(thd);
/*
As a disk space optimization, future masters will not log an event for
LAST_INSERT_ID() if that function returned 0 (and thus they will be able
@@ -4946,7 +4941,22 @@ error:
thd->catalog= 0;
thd->set_db(NULL, 0); /* will free the current database */
thd->set_query(NULL, 0);
+ thd->stmt_da->can_overwrite_status= TRUE;
+ thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
+ thd->stmt_da->can_overwrite_status= FALSE;
close_thread_tables(thd);
+ /*
+ - If inside a multi-statement transaction,
+ defer the release of metadata locks until the current
+ transaction is either committed or rolled back. This prevents
+ other statements from modifying the table for the entire
+ duration of this transaction. This provides commit ordering
+ and guarantees serializability across multiple transactions.
+ - If in autocommit mode, or outside a transactional context,
+ automatically release metadata locks of the current statement.
+ */
+ if (! thd->in_multi_stmt_transaction_mode())
+ thd->mdl_context.release_transactional_locks();
DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error",
thd->is_slave_error= 0; thd->is_fatal_error= 1;);
@@ -5531,11 +5541,9 @@ int Xid_log_event::do_apply_event(Relay_log_info const *rli)
/* For a slave Xid_log_event is COMMIT */
general_log_print(thd, COM_QUERY,
"COMMIT /* implicit, from Xid_log_event */");
- if (!(res= trans_commit(thd)))
- {
- close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
- }
+ res= trans_commit(thd); /* Automatically rolls back on error. */
+ thd->mdl_context.release_transactional_locks();
+
return res;
}
@@ -7610,8 +7618,6 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
We should not honour --slave-skip-errors at this point as we are
having severe errors which should not be skiped.
*/
- mysql_unlock_tables(thd, thd->lock);
- thd->lock= 0;
thd->is_slave_error= 1;
const_cast<Relay_log_info*>(rli)->slave_close_thread_tables(thd);
DBUG_RETURN(ERR_BAD_TABLE_DEF);