From e879caf845f3f1209eb2065fc4463a293ad9518c Mon Sep 17 00:00:00 2001 From: Ashish Agarwal Date: Tue, 2 Jul 2013 11:58:39 +0530 Subject: WL#7076: Backporting wl6715 to support both formats in 5.5, 5.6, 5.7 Backporting wl6715 to mysql-5.5 --- sql/sql_parse.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sql/sql_parse.cc') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ef3454ec9c9..dd9dc53be71 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4806,8 +4806,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if (!(sctx->master_access & SELECT_ACL)) { if (db && (!thd->db || db_is_pattern || strcmp(db, thd->db))) - db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, - db_is_pattern); + db_access= acl_get(sctx->get_host()->ptr(), sctx->get_ip()->ptr(), + sctx->priv_user, db, db_is_pattern); else { /* get access for current db */ @@ -4855,8 +4855,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, } if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db))) - db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, - db_is_pattern); + db_access= acl_get(sctx->get_host()->ptr(), sctx->get_ip()->ptr(), + sctx->priv_user, db, db_is_pattern); else db_access= sctx->db_access; DBUG_PRINT("info",("db_access: %lu want_access: %lu", -- cgit v1.2.1 From fc2c66929737594f5d6b31a25c65e1ec4a524664 Mon Sep 17 00:00:00 2001 From: Dmitry Lenev Date: Tue, 20 Aug 2013 13:12:34 +0400 Subject: Fix for bug#14188793 - "DEADLOCK CAUSED BY ALTER TABLE DOEN'T CLEAR STATUS OF ROLLBACKED TRANSACTION" and bug #17054007 - "TRANSACTION IS NOT FULLY ROLLED BACK IN CASE OF INNODB DEADLOCK". The problem in the first bug report was that although deadlock involving metadata locks was reported using the same error code and message as InnoDB deadlock it didn't rollback transaction like the latter. This caused confusion to users as in some cases after ER_LOCK_DEADLOCK transaction could have been restarted immediately and in some cases rollback was required. The problem in the second bug report was that although InnoDB deadlock caused transaction rollback in all storage engines it didn't cause release of metadata locks. So concurrent DDL on the tables used in transaction was blocked until implicit or explicit COMMIT or ROLLBACK was issued in the connection which got InnoDB deadlock. The former issue has stemmed from the fact that when support for detection and reporting metadata locks deadlocks was added we erroneously assumed that InnoDB doesn't rollback transaction on deadlock but only last statement (while this is what happens on InnoDB lock timeout actually) and so didn't implement rollback of transactions on MDL deadlocks. The latter issue was caused by the fact that rollback of transaction due to deadlock is carried out by setting THD::transaction_rollback_request flag at the point where deadlock is detected and performing rollback inside of trans_rollback_stmt() call when this flag is set. And trans_rollback_stmt() is not aware of MDL locks, so no MDL locks are released. This patch solves these two problems in the following way: - In case when MDL deadlock is detect transaction rollback is requested by setting THD::transaction_rollback_request flag. - Code performing rollback of transaction if THD::transaction_rollback_request is moved out from trans_rollback_stmt(). Now we handle rollback request on the same level as we call trans_rollback_stmt() and release statement/ transaction MDL locks. --- sql/sql_parse.cc | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) (limited to 'sql/sql_parse.cc') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ef3454ec9c9..dac42457a87 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 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 @@ -1183,6 +1183,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; } @@ -1833,7 +1845,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); @@ -1884,6 +1896,13 @@ mysql_execute_command(THD *thd) #endif 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 @@ -2070,8 +2089,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; @@ -4503,7 +4522,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); -- cgit v1.2.1 From 3b1e98d21844b0f32f6e5fe9df447046eb471453 Mon Sep 17 00:00:00 2001 From: Praveenkumar Hulakund Date: Wed, 21 Aug 2013 10:39:40 +0530 Subject: Bug#11765252 - READ OF FREED MEMORY WHEN "USE DB" AND "SHOW PROCESSLIST" Analysis: ---------- The problem here is, if one connection changes its default db and at the same time another connection executes "SHOW PROCESSLIST", when it wants to read db of the another connection then there is a chance of accessing the invalid memory. The db name stored in THD is not guarded while changing user DB and while reading the user DB in "SHOW PROCESSLIST". So, if THD.db is freed by thd "owner" thread and if another thread executing "SHOW PROCESSLIST" statement tries to read and copy THD.db at the same time then we may endup in the issue reported here. Fix: ---------- Used mutex "LOCK_thd_data" to guard THD.db while freeing it and while copying it to processlist. --- sql/sql_parse.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sql/sql_parse.cc') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 457be355f81..d9d9a603869 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1231,7 +1231,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (save_user_connect) decrease_user_connections(save_user_connect); #endif /* NO_EMBEDDED_ACCESS_CHECKS */ + pthread_mutex_lock(&thd->LOCK_thd_data); x_free(save_db); + pthread_mutex_unlock(&thd->LOCK_thd_data); x_free(save_security_ctx.user); } break; -- cgit v1.2.1