diff options
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r-- | sql/sql_parse.cc | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e9adc3b669f..41b809774ad 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2008, 2012, Monty Program Ab +/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. + Copyright (c) 2008, 2013, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1229,6 +1229,18 @@ bool dispatch_command(enum enum_server_command command, THD *thd, close_thread_tables(thd); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); + if (thd->transaction_rollback_request) + { + /* + Transaction rollback was requested since MDL deadlock was + discovered while trying to open tables. Rollback transaction + in all storage engines including binary log and release all + locks. + */ + trans_rollback_implicit(thd); + thd->mdl_context.release_transactional_locks(); + } + thd->cleanup_after_query(); break; } @@ -1899,7 +1911,7 @@ err: can free its locks if LOCK TABLES locked some tables before finding that it can't lock a table in its list */ - trans_commit_implicit(thd); + trans_rollback(thd); /* Close tables and release metadata locks. */ close_thread_tables(thd); DBUG_ASSERT(!thd->locked_tables_mode); @@ -1951,6 +1963,13 @@ mysql_execute_command(THD *thd) DBUG_ASSERT(thd->transaction.stmt.is_empty() || thd->in_sub_stmt); /* + Each statement or replication event which might produce deadlock + should handle transaction rollback on its own. So by the start of + the next statement transaction rollback request should be fulfilled + already. + */ + DBUG_ASSERT(! thd->transaction_rollback_request || thd->in_sub_stmt); + /* In many cases first table of main SELECT_LEX have special meaning => check that it is first table in global list and relink it first in queries_tables list if it is necessary (we need such relinking only @@ -2138,8 +2157,8 @@ mysql_execute_command(THD *thd) or triggers as all such statements prohibited there. */ DBUG_ASSERT(! thd->in_sub_stmt); - /* Commit or rollback the statement transaction. */ - thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd); + /* Statement transaction still should not be started. */ + DBUG_ASSERT(thd->transaction.stmt.is_empty()); /* Commit the normal transaction if one is active. */ if (trans_commit_implicit(thd)) goto error; @@ -4567,7 +4586,17 @@ finish: DEBUG_SYNC(thd, "execute_command_after_close_tables"); #endif - if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END)) + if (! thd->in_sub_stmt && thd->transaction_rollback_request) + { + /* + We are not in sub-statement and transaction rollback was requested by + one of storage engines (e.g. due to deadlock). Rollback transaction in + all storage engines including binary log. + */ + trans_rollback_implicit(thd); + thd->mdl_context.release_transactional_locks(); + } + else if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END)) { /* No transaction control allowed in sub-statements. */ DBUG_ASSERT(! thd->in_sub_stmt); |