summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-10-18 16:36:24 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-10-18 16:36:24 +0300
commit9c5835e067e99e1f85477f28d3bdc807537393a8 (patch)
tree644c828a4812ab1f0fffb3ada2deb5822997ce46 /storage
parent78e023c2743c9b7fc17db31cc11524920b658075 (diff)
parent18eab4a83280049974265358b0d78389d05cd67b (diff)
downloadmariadb-git-9c5835e067e99e1f85477f28d3bdc807537393a8.tar.gz
Merge 10.5 into 10.6
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/include/lock0lock.h4
-rw-r--r--storage/innobase/lock/lock0lock.cc118
-rw-r--r--storage/innobase/trx/trx0trx.cc14
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/mdev_26539.result36
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/mdev_26539.cnf3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/mdev_26539.test40
-rw-r--r--storage/spider/spd_trx.cc6
7 files changed, 217 insertions, 4 deletions
diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h
index c2fef3baaac..5f051b8ffbe 100644
--- a/storage/innobase/include/lock0lock.h
+++ b/storage/innobase/include/lock0lock.h
@@ -427,6 +427,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);
+
/** Release locks on a table whose creation is being rolled back */
ATTRIBUTE_COLD void lock_release_on_rollback(trx_t *trx, dict_table_t *table);
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 47e30e075a0..dcef069f049 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -3883,6 +3883,124 @@ released:
#endif
}
+/** Release non-exclusive locks on XA PREPARE,
+and wake up possible other transactions waiting because of these locks.
+@param trx transaction in XA PREPARE state
+@return whether all locks were released */
+static bool lock_release_on_prepare_try(trx_t *trx)
+{
+ /* At this point, trx->lock.trx_locks can still be modified by other
+ threads to convert implicit exclusive locks into explicit ones.
+
+ The function lock_table_create() should never be invoked on behalf
+ of a transaction that is running in another thread. Also there, we
+ will assert that the current transaction be active. */
+ DBUG_ASSERT(trx->state == TRX_STATE_PREPARED);
+
+ bool all_released= true;
+ lock_sys.rd_lock(SRW_LOCK_CALL);
+ trx->mutex_lock();
+
+ /* Note: Normally, trx->mutex is not held while acquiring
+ a lock table latch, but here we are following the opposite order.
+ To avoid deadlocks, we only try to acquire the lock table latches
+ but not keep waiting for them. */
+
+ for (lock_t *prev, *lock= UT_LIST_GET_LAST(trx->lock.trx_locks); lock;
+ lock= prev)
+ {
+ ut_ad(lock->trx == trx);
+ prev= UT_LIST_GET_PREV(trx_locks, lock);
+ if (!lock->is_table())
+ {
+ ut_ad(!lock->index->table->is_temporary());
+ if (lock->mode() == LOCK_X && !lock->is_gap())
+ continue;
+ auto &lock_hash= lock_sys.hash_get(lock->type_mode);
+ auto cell= lock_hash.cell_get(lock->un_member.rec_lock.page_id.fold());
+ auto latch= lock_sys_t::hash_table::latch(cell);
+ if (latch->try_acquire())
+ {
+ lock_rec_dequeue_from_page(lock, false);
+ latch->release();
+ }
+ else
+ all_released= false;
+ }
+ else
+ {
+ dict_table_t *table= lock->un_member.tab_lock.table;
+ ut_ad(!table->is_temporary());
+ switch (lock->mode()) {
+ case LOCK_IS:
+ case LOCK_S:
+ if (table->lock_mutex_trylock())
+ {
+ lock_table_dequeue(lock, false);
+ table->lock_mutex_unlock();
+ }
+ else
+ all_released= false;
+ break;
+ case LOCK_IX:
+ case LOCK_X:
+ ut_ad(table->id >= DICT_HDR_FIRST_ID || trx->dict_operation);
+ /* fall through */
+ default:
+ break;
+ }
+ }
+ }
+
+ lock_sys.rd_unlock();
+ trx->mutex_unlock();
+ return all_released;
+}
+
+/** 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)
+{
+ for (ulint count= 5; count--; )
+ if (lock_release_on_prepare_try(trx))
+ return;
+
+ LockMutexGuard g{SRW_LOCK_CALL};
+ trx->mutex_lock();
+
+ for (lock_t *prev, *lock= UT_LIST_GET_LAST(trx->lock.trx_locks); lock;
+ lock= prev)
+ {
+ ut_ad(lock->trx == trx);
+ prev= UT_LIST_GET_PREV(trx_locks, lock);
+ if (!lock->is_table())
+ {
+ ut_ad(!lock->index->table->is_temporary());
+ if (lock->mode() != LOCK_X || lock->is_gap())
+ lock_rec_dequeue_from_page(lock, false);
+ }
+ else
+ {
+ dict_table_t *table= lock->un_member.tab_lock.table;
+ ut_ad(!table->is_temporary());
+ switch (lock->mode()) {
+ case LOCK_IS:
+ case LOCK_S:
+ lock_table_dequeue(lock, false);
+ break;
+ case LOCK_IX:
+ case LOCK_X:
+ ut_ad(table->id >= DICT_HDR_FIRST_ID || trx->dict_operation);
+ /* fall through */
+ default:
+ break;
+ }
+ }
+ }
+
+ trx->mutex_unlock();
+}
+
/** Release locks on a table whose creation is being rolled back */
ATTRIBUTE_COLD void lock_release_on_rollback(trx_t *trx, dict_table_t *table)
{
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index ad49d3e9c8e..43ef05f4f2b 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -1868,6 +1868,20 @@ 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_SERIALIZABLE) {
+ /* Do not release any locks at the
+ SERIALIZABLE isolation level. */
+ } else if (!trx->mysql_thd
+ || thd_sql_command(trx->mysql_thd)
+ != SQLCOM_XA_PREPARE) {
+ /* Do not release locks for XA COMMIT ONE PHASE
+ or for internal distributed transactions
+ (XID::get_my_xid() would be nonzero). */
+ } else {
+ lock_release_on_prepare(trx);
+ }
}
}
diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_26539.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_26539.result
new file mode 100644
index 00000000000..4e195fddfad
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_26539.result
@@ -0,0 +1,36 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+#
+# MDEV-26539 SIGSEGV in spider_check_and_set_trx_isolation and I_P_List_iterator from THD::drop_temporary_table (10.5.3 opt only) on ALTER
+#
+connection child2_1;
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+CREATE TABLE tbl_a (
+c INT
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+CREATE TABLE tbl_a (
+c INT
+) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='table "tbl_a"' PARTITION BY LIST COLUMNS (c) (
+PARTITION pt1 DEFAULT COMMENT = 'srv "s_2_1"'
+);
+INSERT INTO tbl_a VALUES (1);
+ALTER TABLE tbl_a CHECK PARTITION ALL;
+Table Op Msg_type Msg_text
+auto_test_local.tbl_a check status OK
+DROP DATABASE auto_test_local;
+connection child2_1;
+DROP DATABASE auto_test_remote;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_26539.cnf b/storage/spider/mysql-test/spider/bugfix/t/mdev_26539.cnf
new file mode 100644
index 00000000000..05dfd8a0bce
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_26539.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_26539.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_26539.test
new file mode 100644
index 00000000000..f2561f8c9a5
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_26539.test
@@ -0,0 +1,40 @@
+--disable_query_log
+--disable_result_log
+--source ../../t/test_init.inc
+--enable_result_log
+--enable_query_log
+
+--echo #
+--echo # MDEV-26539 SIGSEGV in spider_check_and_set_trx_isolation and I_P_List_iterator from THD::drop_temporary_table (10.5.3 opt only) on ALTER
+--echo #
+
+--connection child2_1
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+eval CREATE TABLE tbl_a (
+ c INT
+) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+
+--connection master_1
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+eval CREATE TABLE tbl_a (
+ c INT
+) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='table "tbl_a"' PARTITION BY LIST COLUMNS (c) (
+ PARTITION pt1 DEFAULT COMMENT = 'srv "s_2_1"'
+);
+
+INSERT INTO tbl_a VALUES (1);
+ALTER TABLE tbl_a CHECK PARTITION ALL;
+
+DROP DATABASE auto_test_local;
+
+--connection child2_1
+DROP DATABASE auto_test_remote;
+
+--disable_query_log
+--disable_result_log
+--source ../../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc
index defa9be3f8c..c5095e7ff55 100644
--- a/storage/spider/spd_trx.cc
+++ b/storage/spider/spd_trx.cc
@@ -3802,10 +3802,8 @@ int spider_check_trx_and_get_conn(
}
spider->wide_handler->trx = trx;
spider->set_error_mode();
- if (
- spider->wide_handler->sql_command != SQLCOM_DROP_TABLE &&
- spider->wide_handler->sql_command != SQLCOM_ALTER_TABLE
- ) {
+ if (spider->wide_handler->sql_command != SQLCOM_DROP_TABLE)
+ {
SPIDER_TRX_HA *trx_ha = spider_check_trx_ha(trx, spider);
if (!trx_ha || trx_ha->wait_for_reusing)
spider_trx_set_link_idx_for_all(spider);