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

Merge tag 'mysql-5.5.45' into 5.5

This commit is contained in:
Sergei Golubchik
2015-08-01 14:56:18 +02:00
16 changed files with 486 additions and 50 deletions

View File

@ -4064,10 +4064,11 @@ request_backoff_action(enum_open_table_action action_arg,
* We met a broken table that needs repair, or a table that
is not present on this MySQL server and needs re-discovery.
To perform the action, we need an exclusive metadata lock on
the table. Acquiring an X lock while holding other shared
locks is very deadlock-prone. If this is a multi- statement
transaction that holds metadata locks for completed
statements, we don't do it, and report an error instead.
the table. Acquiring X lock while holding other shared
locks can easily lead to deadlocks. We rely on MDL deadlock
detector to discover them. If this is a multi-statement
transaction that holds metadata locks for completed statements,
we should keep these locks after discovery/repair.
The action type in this case is OT_DISCOVER or OT_REPAIR.
* Our attempt to acquire an MDL lock lead to a deadlock,
detected by the MDL deadlock detector. The current
@ -4108,7 +4109,7 @@ request_backoff_action(enum_open_table_action action_arg,
keep tables open between statements and a livelock
is not possible.
*/
if (action_arg != OT_REOPEN_TABLES && m_has_locks)
if (action_arg == OT_BACKOFF_AND_RETRY && m_has_locks)
{
my_error(ER_LOCK_DEADLOCK, MYF(0));
m_thd->mark_transaction_to_rollback(true);
@ -4135,6 +4136,32 @@ request_backoff_action(enum_open_table_action action_arg,
}
/**
An error handler to mark transaction to rollback on DEADLOCK error
during DISCOVER / REPAIR.
*/
class MDL_deadlock_discovery_repair_handler : public Internal_error_handler
{
public:
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
{
if (sql_errno == ER_LOCK_DEADLOCK)
{
thd->mark_transaction_to_rollback(true);
}
/*
We have marked this transaction to rollback. Return false to allow
error to be reported or handled by other handlers.
*/
return false;
}
};
/**
Recover from failed attempt of open table by performing requested action.
@ -4150,6 +4177,12 @@ Open_table_context::
recover_from_failed_open()
{
bool result= FALSE;
MDL_deadlock_discovery_repair_handler handler;
/*
Install error handler to mark transaction to rollback on DEADLOCK error.
*/
m_thd->push_internal_handler(&handler);
/* Execute the action. */
switch (m_action)
{
@ -4171,7 +4204,12 @@ recover_from_failed_open()
m_thd->warning_info->clear_warning_info(m_thd->query_id);
m_thd->clear_error(); // Clear error message
m_thd->mdl_context.release_transactional_locks();
/*
Rollback to start of the current statement to release exclusive lock
on table which was discovered but preserve locks from previous statements
in current transaction.
*/
m_thd->mdl_context.rollback_to_savepoint(start_of_statement_svp());
break;
}
case OT_REPAIR:
@ -4185,12 +4223,18 @@ recover_from_failed_open()
m_failed_table->table_name, FALSE);
result= auto_repair_table(m_thd, m_failed_table);
m_thd->mdl_context.release_transactional_locks();
/*
Rollback to start of the current statement to release exclusive lock
on table which was discovered but preserve locks from previous statements
in current transaction.
*/
m_thd->mdl_context.rollback_to_savepoint(start_of_statement_svp());
break;
}
default:
DBUG_ASSERT(0);
}
m_thd->pop_internal_handler();
/*
Reset the pointers to conflicting MDL request and the
TABLE_LIST element, set when we need auto-discovery or repair,