summaryrefslogtreecommitdiff
path: root/sql/handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/handler.cc')
-rw-r--r--sql/handler.cc40
1 files changed, 32 insertions, 8 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index eb060002f48..22bb3069a9f 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -29,8 +29,6 @@
#include "sql_cache.h" // query_cache, query_cache_*
#include "key.h" // key_copy, key_unpack, key_cmp_if_same, key_cmp
#include "sql_table.h" // build_table_filename
-#include "lock.h" // wait_if_global_read_lock,
- // start_waiting_global_read_lock
#include "sql_parse.h" // check_stack_overrun
#include "sql_acl.h" // SUPER_ACL
#include "sql_base.h" // free_io_cache
@@ -41,6 +39,7 @@
#include "transaction.h"
#include <errno.h>
#include "probes_mysql.h"
+#include "debug_sync.h" // DEBUG_SYNC
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
@@ -1155,6 +1154,7 @@ int ha_commit_trans(THD *thd, bool all)
{
uint rw_ha_count;
bool rw_trans;
+ MDL_request mdl_request;
DBUG_EXECUTE_IF("crash_commit_before", DBUG_SUICIDE(););
@@ -1166,11 +1166,27 @@ int ha_commit_trans(THD *thd, bool all)
/* rw_trans is TRUE when we in a transaction changing data */
rw_trans= is_real_trans && (rw_ha_count > 0);
- if (rw_trans &&
- thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, FALSE))
+ if (rw_trans)
{
- ha_rollback_trans(thd, all);
- DBUG_RETURN(1);
+ /*
+ Acquire a metadata lock which will ensure that COMMIT is blocked
+ by an active FLUSH TABLES WITH READ LOCK (and vice versa:
+ COMMIT in progress blocks FTWRL).
+
+ We allow the owner of FTWRL to COMMIT; we assume that it knows
+ what it does.
+ */
+ mdl_request.init(MDL_key::COMMIT, "", "", MDL_INTENTION_EXCLUSIVE,
+ MDL_EXPLICIT);
+
+ if (thd->mdl_context.acquire_lock(&mdl_request,
+ thd->variables.lock_wait_timeout))
+ {
+ ha_rollback_trans(thd, all);
+ DBUG_RETURN(1);
+ }
+
+ DEBUG_SYNC(thd, "ha_commit_trans_after_acquire_commit_lock");
}
if (rw_trans &&
@@ -1225,8 +1241,16 @@ int ha_commit_trans(THD *thd, bool all)
DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE(););
RUN_HOOK(transaction, after_commit, (thd, FALSE));
end:
- if (rw_trans)
- thd->global_read_lock.start_waiting_global_read_lock(thd);
+ if (rw_trans && mdl_request.ticket)
+ {
+ /*
+ We do not always immediately release transactional locks
+ after ha_commit_trans() (see uses of ha_enable_transaction()),
+ thus we release the commit blocker lock as soon as it's
+ not needed.
+ */
+ thd->mdl_context.release_lock(mdl_request.ticket);
+ }
}
/* Free resources and perform other cleanup even for 'empty' transactions. */
else if (is_real_trans)