diff options
author | Sergei Golubchik <serg@mariadb.org> | 2015-08-05 09:45:17 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2015-08-05 09:45:17 +0200 |
commit | 928edb5a9139502abf6e1c1b1552234b39d38a78 (patch) | |
tree | fe03d1ee611b2800c4b68aadb559bad3865f34d1 /sql/sql_base.cc | |
parent | 1610c4285aa2a3421cca9983360ff33e86936479 (diff) | |
parent | fa51f70dc68fe2f3afe943e2c81fcbdb34f16cad (diff) | |
download | mariadb-git-928edb5a9139502abf6e1c1b1552234b39d38a78.tar.gz |
Merge branch '5.5' into 10.0
5.5 without InnoDB/XtraDB changes
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 58 |
1 files changed, 51 insertions, 7 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 643ad4b41cb..12cd999d130 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3409,10 +3409,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 @@ -3453,7 +3454,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); @@ -3482,6 +3483,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, + Sql_condition::enum_warning_level level, + const char* msg, + Sql_condition ** 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. @pre This function should be called only with "action" != OT_NO_ACTION @@ -3495,6 +3522,12 @@ bool 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) { @@ -3530,7 +3563,12 @@ Open_table_context::recover_from_failed_open() result= FALSE; } - 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: @@ -3543,12 +3581,18 @@ Open_table_context::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, |