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:
@ -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,
|
||||
|
Reference in New Issue
Block a user