summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-05-26 11:54:55 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-05-26 11:54:55 +0300
commitca38b6e42791a6edbd3cc0b626a8d06b7776e76b (patch)
treef0b9f34521554ce94ef9a5bd6c7e5f595459240f /storage
parentea7830eef48333e28f98a9b91f05a95735b465a3 (diff)
parent7476e8c7cdd73d60294126a2840baee97e7644b6 (diff)
downloadmariadb-git-ca38b6e42791a6edbd3cc0b626a8d06b7776e76b.tar.gz
Merge 10.3 into 10.4
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/handler/ha_innodb.cc30
-rw-r--r--storage/innobase/include/ut0pool.h10
-rw-r--r--storage/innobase/row/row0log.cc18
-rw-r--r--storage/innobase/trx/trx0trx.cc22
4 files changed, 63 insertions, 17 deletions
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 4c2b4fb2693..e9c555e3ffc 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3395,7 +3395,7 @@ ha_innobase::reset_template(void)
/* Force table to be freed in close_thread_table(). */
DBUG_EXECUTE_IF("free_table_in_fts_query",
if (m_prebuilt->in_fts_query) {
- table->m_needs_reopen = true;
+ table->mark_table_for_reopen();
}
);
@@ -5093,9 +5093,8 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels)
{
DBUG_ENTER("innobase_kill_query");
- if (trx_t *trx= thd_to_trx(thd))
+ if (trx_t* trx= thd_to_trx(thd))
{
- ut_ad(trx->mysql_thd == thd);
#ifdef WITH_WSREP
if (trx->is_wsrep() && wsrep_thd_is_aborting(thd))
/* if victim has been signaled by BF thread and/or aborting is already
@@ -5103,8 +5102,29 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels)
Also, BF thread should own trx mutex for the victim. */
DBUG_VOID_RETURN;
#endif /* WITH_WSREP */
- /* Cancel a pending lock request if there are any */
- lock_trx_handle_wait(trx);
+ lock_mutex_enter();
+ mutex_enter(&trx_sys.mutex);
+ trx_mutex_enter(trx);
+ /* It is possible that innobase_close_connection() is concurrently
+ being executed on our victim. Even if the trx object is later
+ reused for another client connection or a background transaction,
+ its trx->mysql_thd will differ from our thd.
+
+ trx_t::state changes are protected by trx_t::mutex, and
+ trx_sys.trx_list is protected by trx_sys.mutex, in
+ both trx_create() and trx_free().
+
+ At this point, trx may have been reallocated for another client
+ connection, or for a background operation. In that case, either
+ trx_t::state or trx_t::mysql_thd should not match our expectations. */
+ bool cancel= trx->mysql_thd == thd && trx->state == TRX_STATE_ACTIVE &&
+ !trx->lock.was_chosen_as_deadlock_victim;
+ mutex_exit(&trx_sys.mutex);
+ if (!cancel);
+ else if (lock_t *lock= trx->lock.wait_lock)
+ lock_cancel_waiting_and_release(lock);
+ lock_mutex_exit();
+ trx_mutex_exit(trx);
}
DBUG_VOID_RETURN;
diff --git a/storage/innobase/include/ut0pool.h b/storage/innobase/include/ut0pool.h
index 02a4e16bb70..f6006144dc4 100644
--- a/storage/innobase/include/ut0pool.h
+++ b/storage/innobase/include/ut0pool.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2013, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2018, 2020, 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
@@ -86,11 +87,15 @@ struct Pool {
for (Element* elem = m_start; elem != m_last; ++elem) {
ut_ad(elem->m_pool == this);
+#ifdef __SANITIZE_ADDRESS__
/* Unpoison the memory for AddressSanitizer */
MEM_UNDEFINED(&elem->m_type, sizeof elem->m_type);
+#endif
+#ifdef HAVE_valgrind
/* Declare the contents as initialized for Valgrind;
we checked this in mem_free(). */
UNIV_MEM_VALID(&elem->m_type, sizeof elem->m_type);
+#endif
Factory::destroy(&elem->m_type);
}
@@ -127,13 +132,18 @@ struct Pool {
#if defined HAVE_valgrind || defined __SANITIZE_ADDRESS__
if (elem) {
+# ifdef __SANITIZE_ADDRESS__
/* Unpoison the memory for AddressSanitizer */
MEM_UNDEFINED(&elem->m_type, sizeof elem->m_type);
+# endif
+# ifdef HAVE_valgrind
+
/* Declare the memory initialized for Valgrind.
The trx_t that are released to the pool are
actually initialized; we checked that by
UNIV_MEM_ASSERT_RW() in mem_free() below. */
UNIV_MEM_VALID(&elem->m_type, sizeof elem->m_type);
+# endif
}
#endif
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index 60b8fdf06b2..eece00fc267 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -1177,19 +1177,15 @@ row_log_table_get_pk_col(
return(DB_INVALID_NULL);
}
- ulint new_i = dict_col_get_clust_pos(ifield->col, index);
-
- if (UNIV_UNLIKELY(new_i >= log->defaults->n_fields)) {
- ut_ad(0);
- return DB_INVALID_NULL;
- }
+ unsigned col_no= ifield->col->ind;
+ ut_ad(col_no < log->defaults->n_fields);
field = static_cast<const byte*>(
- log->defaults->fields[new_i].data);
+ log->defaults->fields[col_no].data);
if (!field) {
return(DB_INVALID_NULL);
}
- len = log->defaults->fields[new_i].len;
+ len = log->defaults->fields[col_no].len;
}
if (rec_offs_nth_extern(offsets, i)) {
@@ -1671,10 +1667,12 @@ blob_done:
const dfield_t& default_field
= log->defaults->fields[col_no];
- Field* field = log->old_table->field[col_no];
+
+ Field* field = log->old_table->field[col->ind];
field->set_warning(Sql_condition::WARN_LEVEL_WARN,
- WARN_DATA_TRUNCATED, 1, ulong(log->n_rows));
+ WARN_DATA_TRUNCATED, 1,
+ ulong(log->n_rows));
if (!log->allow_not_null) {
/* We got a NULL value for a NOT NULL column. */
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 276a78d00bf..d78cbcac521 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -455,12 +455,30 @@ void trx_free(trx_t*& trx)
ut_ad(trx->will_lock == 0);
trx_pools->mem_free(trx);
+#ifdef __SANITIZE_ADDRESS__
/* Unpoison the memory for innodb_monitor_set_option;
it is operating also on the freed transaction objects. */
MEM_UNDEFINED(&trx->mutex, sizeof trx->mutex);
- /* Declare the contents as initialized for Valgrind;
- we checked that it was initialized in trx_pools->mem_free(trx). */
+ /* For innobase_kill_connection() */
+# ifdef WITH_WSREP
+ MEM_UNDEFINED(&trx->wsrep, sizeof trx->wsrep);
+# endif
+ MEM_UNDEFINED(&trx->state, sizeof trx->state);
+ MEM_UNDEFINED(&trx->mysql_thd, sizeof trx->mysql_thd);
+#endif
+#ifdef HAVE_valgrind
+ /* Unpoison the memory for innodb_monitor_set_option;
+ it is operating also on the freed transaction objects.
+ We checked that these were initialized in
+ trx_pools->mem_free(trx). */
UNIV_MEM_VALID(&trx->mutex, sizeof trx->mutex);
+ /* For innobase_kill_connection() */
+# ifdef WITH_WSREP
+ UNIV_MEM_VALID(&trx->wsrep, sizeof trx->wsrep);
+# endif
+ UNIV_MEM_VALID(&trx->state, sizeof trx->state);
+ UNIV_MEM_VALID(&trx->mysql_thd, sizeof trx->mysql_thd);
+#endif
trx = NULL;
}