summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--storage/innobase/include/lock0lock.h6
-rw-r--r--storage/innobase/lock/lock0lock.cc59
-rw-r--r--storage/innobase/trx/trx0trx.cc5
3 files changed, 69 insertions, 1 deletions
diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h
index 3b63b06a9bb..225c246f4e7 100644
--- a/storage/innobase/include/lock0lock.h
+++ b/storage/innobase/include/lock0lock.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2020, MariaDB Corporation.
+Copyright (c) 2017, 2021, MariaDB Corporation.
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 the Free Software
@@ -478,6 +478,10 @@ lock_rec_unlock(
and release possible other transactions waiting because of these locks. */
void lock_release(trx_t* trx);
+/** Release non-exclusive locks on XA PREPARE,
+and release possible other transactions waiting because of these locks. */
+void lock_release_on_prepare(trx_t *trx);
+
/*************************************************************//**
Get the lock hash table */
UNIV_INLINE
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 8dc2d7c585a..7b1af2e6a6c 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -4219,6 +4219,65 @@ void lock_release(trx_t* trx)
#endif
}
+/** Release non-exclusive locks on XA PREPARE,
+and release possible other transactions waiting because of these locks. */
+void lock_release_on_prepare(trx_t *trx)
+{
+ ulint count= 0;
+ lock_mutex_enter();
+ ut_ad(!trx_mutex_own(trx));
+
+ for (lock_t *lock= UT_LIST_GET_LAST(trx->lock.trx_locks); lock; )
+ {
+ ut_ad(lock->trx == trx);
+
+ if (lock_get_type_low(lock) == LOCK_REC)
+ {
+ ut_ad(!lock->index->table->is_temporary());
+ if (lock_rec_get_gap(lock) || lock_get_mode(lock) != LOCK_X)
+ lock_rec_dequeue_from_page(lock);
+ else
+ {
+ ut_ad(trx->dict_operation ||
+ lock->index->table->id >= DICT_HDR_FIRST_ID);
+retain_lock:
+ lock= UT_LIST_GET_PREV(trx_locks, lock);
+ continue;
+ }
+ }
+ else
+ {
+ ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
+ dict_table_t *table= lock->un_member.tab_lock.table;
+ ut_ad(!table->is_temporary());
+
+ switch (lock_get_mode(lock)) {
+ case LOCK_IS:
+ case LOCK_S:
+ lock_table_dequeue(lock);
+ break;
+ case LOCK_IX:
+ case LOCK_X:
+ ut_ad(table->id >= DICT_HDR_FIRST_ID || trx->dict_operation);
+ /* fall through */
+ default:
+ goto retain_lock;
+ }
+ }
+
+ if (++count == LOCK_RELEASE_INTERVAL)
+ {
+ lock_mutex_exit();
+ count= 0;
+ lock_mutex_enter();
+ }
+
+ lock= UT_LIST_GET_LAST(trx->lock.trx_locks);
+ }
+
+ lock_mutex_exit();
+}
+
/* True if a lock mode is S or X */
#define IS_LOCK_S_OR_X(lock) \
(lock_get_mode(lock) == LOCK_S \
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index cf8fa17cf1a..3cb9ab5f320 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -1971,6 +1971,11 @@ trx_prepare(
We must not be holding any mutexes or latches here. */
trx_flush_log_if_needed(lsn, trx);
+
+ if (UT_LIST_GET_LEN(trx->lock.trx_locks)
+ && trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
+ lock_release_on_prepare(trx);
+ }
}
}