summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc41
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);