1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Bug#24989: The DEADLOCK error is improperly handled by InnoDB.

When innodb detects a deadlock it calls ha_rollback_trans() to rollback the 
main transaction. But such action isn't allowed from inside of triggers and
functions. When it happen the 'Explicit or implicit commit' error is thrown
even if there is no commit/rollback statements in the trigger/function. This
leads to the user confusion.

Now the convert_error_code_to_mysql() function doesn't call the 
ha_rollback_trans() function directly but rather calls the
mark_transaction_to_rollback function and returns an error.
The sp_rcontext::find_handler() now doesn't allow errors to be caught by the
trigger/function error handlers when the thd->is_fatal_sub_stmt_error flag
is set. Procedures are still allowed to catch such errors.
The sp_rcontext::find_handler function now accepts a THD handle as a parameter.
The transaction_rollback_request and the is_fatal_sub_stmt_error flags are 
added to the THD class. The are initialized by the THD class constructor.
Now the ha_autocommit_or_rollback function rolls back main transaction
when not in a sub statement and the thd->transaction_rollback_request
is set.
The THD::restore_sub_statement_state function now resets the 
thd->is_fatal_sub_stmt_error flag on exit from a sub-statement.
This commit is contained in:
evgen@moonbone.local
2007-07-30 17:14:34 +04:00
parent debb054d4a
commit 8de5603d1d
8 changed files with 250 additions and 15 deletions

View File

@ -173,6 +173,7 @@ THD::THD()
Open_tables_state(refresh_version),
lock_id(&main_lock_id),
user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0),
transaction_rollback_request(0), is_fatal_sub_stmt_error(0),
rand_used(0), time_zone_used(0),
last_insert_id_used(0), last_insert_id_used_bin_log(0), insert_id_used(0),
clear_next_insert_id(0), in_lock_tables(0), bootstrap(0),
@ -967,7 +968,7 @@ void select_send::abort()
{
DBUG_ENTER("select_send::abort");
if (status && thd->spcont &&
thd->spcont->find_handler(thd->net.last_errno,
thd->spcont->find_handler(thd, thd->net.last_errno,
MYSQL_ERROR::WARN_LEVEL_ERROR))
{
/*
@ -2150,6 +2151,13 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup)
limit_found_rows= backup->limit_found_rows;
sent_row_count= backup->sent_row_count;
client_capabilities= backup->client_capabilities;
/*
If we've left sub-statement mode, reset the fatal error flag.
Otherwise keep the current value, to propagate it up the sub-statement
stack.
*/
if (!in_sub_stmt)
is_fatal_sub_stmt_error= FALSE;
if ((options & OPTION_BIN_LOG) && is_update_query(lex->sql_command))
mysql_bin_log.stop_union_events(this);
@ -2163,6 +2171,18 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup)
}
/**
Mark transaction to rollback and mark error as fatal to a sub-statement.
@param thd Thread handle
@param all TRUE <=> rollback main transaction.
*/
void mark_transaction_to_rollback(THD *thd, bool all)
{
thd->is_fatal_sub_stmt_error= TRUE;
thd->transaction_rollback_request= all;
}
/***************************************************************************
Handling of XA id cacheing
***************************************************************************/