diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-10-18 16:36:24 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-10-18 16:36:24 +0300 |
commit | 9c5835e067e99e1f85477f28d3bdc807537393a8 (patch) | |
tree | 644c828a4812ab1f0fffb3ada2deb5822997ce46 /storage | |
parent | 78e023c2743c9b7fc17db31cc11524920b658075 (diff) | |
parent | 18eab4a83280049974265358b0d78389d05cd67b (diff) | |
download | mariadb-git-9c5835e067e99e1f85477f28d3bdc807537393a8.tar.gz |
Merge 10.5 into 10.6
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/include/lock0lock.h | 4 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 118 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.cc | 14 | ||||
-rw-r--r-- | storage/spider/mysql-test/spider/bugfix/r/mdev_26539.result | 36 | ||||
-rw-r--r-- | storage/spider/mysql-test/spider/bugfix/t/mdev_26539.cnf | 3 | ||||
-rw-r--r-- | storage/spider/mysql-test/spider/bugfix/t/mdev_26539.test | 40 | ||||
-rw-r--r-- | storage/spider/spd_trx.cc | 6 |
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); |