1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-01 17:39:21 +03:00

Remove trx_t::has_search_latch and simplify debug code

When the btr_search_latch was split into an array of latches
in MySQL 5.7.8 as part of the Oracle Bug#20985298 fix, the "caching"
of the latch across storage engine API calls was removed, and
the field trx->has_search_latch would only be set during a short
time frame in the execution of row_search_mvcc(), which was
formerly called row_search_for_mysql().

This means that the column
INFORMATION_SCHEMA.INNODB_TRX.TRX_ADAPTIVE_HASH_LATCHED will always
report 0. That column cannot be removed in MariaDB 10.2, but it
can be removed in future releases.

trx_t::has_search_latch: Remove.

trx_assert_no_search_latch(): Remove.

row_sel_try_search_shortcut_for_mysql(): Remove a redundant condition
on trx->has_search_latch (it was always true).

sync_check_iterate(): Make the parameter const.

sync_check_functor_t: Make the operator() const, and remove result()
and the virtual destructor. There is no need to have mutable state
in the functors.

sync_checker<bool>: Replaces dict_sync_check and btrsea_sync_check.

sync_check: Replaces btrsea_sync_check.

dict_sync_check: Instantiated from sync_checker.

sync_allowed_latches: Use std::find() directly on the array.
Remove the std::vector.

TrxInInnoDB::enter(), TrxInInnoDB::exit(): Remove obviously redundant
debug assertions on trx->in_depth, and use equality comparison against 0
because it could be more efficient on some architectures.
This commit is contained in:
Marko Mäkelä
2017-06-16 12:21:46 +03:00
parent e5980bf1b1
commit 50faeda4d6
17 changed files with 88 additions and 419 deletions

View File

@@ -1,6 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@@ -991,11 +992,7 @@ BtrBulk::finish(dberr_t err)
ut_ad(err == DB_SUCCESS); ut_ad(err == DB_SUCCESS);
} }
#ifdef UNIV_DEBUG ut_ad(!sync_check_iterate(dict_sync_check()));
dict_sync_check check(true);
ut_ad(!sync_check_iterate(check));
#endif /* UNIV_DEBUG */
ut_ad(err != DB_SUCCESS || btr_validate_index(m_index, NULL, false)); ut_ad(err != DB_SUCCESS || btr_validate_index(m_index, NULL, false));
return(err); return(err);

View File

@@ -1870,15 +1870,8 @@ buf_flush_batch(
counts */ counts */
{ {
ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);
ut_ad(flush_type == BUF_FLUSH_LRU
#ifdef UNIV_DEBUG || !sync_check_iterate(dict_sync_check()));
{
dict_sync_check check(true);
ut_ad(flush_type != BUF_FLUSH_LIST
|| !sync_check_iterate(check));
}
#endif /* UNIV_DEBUG */
buf_pool_mutex_enter(buf_pool); buf_pool_mutex_enter(buf_pool);

View File

@@ -6113,14 +6113,7 @@ dict_set_corrupted(
ut_ad(mutex_own(&dict_sys->mutex)); ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(!dict_table_is_comp(dict_sys->sys_tables)); ut_ad(!dict_table_is_comp(dict_sys->sys_tables));
ut_ad(!dict_table_is_comp(dict_sys->sys_indexes)); ut_ad(!dict_table_is_comp(dict_sys->sys_indexes));
ut_ad(!sync_check_iterate(dict_sync_check()));
#ifdef UNIV_DEBUG
{
dict_sync_check check(true);
ut_ad(!sync_check_iterate(check));
}
#endif /* UNIV_DEBUG */
/* Mark the table as corrupted only if the clustered index /* Mark the table as corrupted only if the clustered index
is corrupted */ is corrupted */

View File

@@ -1869,6 +1869,8 @@ void
innobase_srv_conc_exit_innodb( innobase_srv_conc_exit_innodb(
row_prebuilt_t* prebuilt) row_prebuilt_t* prebuilt)
{ {
ut_ad(!sync_check_iterate(sync_check()));
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_on(prebuilt->trx->mysql_thd) && if (wsrep_on(prebuilt->trx->mysql_thd) &&
wsrep_thd_is_BF(prebuilt->trx->mysql_thd, FALSE)) { wsrep_thd_is_BF(prebuilt->trx->mysql_thd, FALSE)) {
@@ -1877,13 +1879,6 @@ innobase_srv_conc_exit_innodb(
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
trx_t* trx = prebuilt->trx; trx_t* trx = prebuilt->trx;
#ifdef BTR_CUR_HASH_ADAPT
# ifdef UNIV_DEBUG
btrsea_sync_check check(trx->has_search_latch);
ut_ad(!sync_check_iterate(check));
# endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
/* This is to avoid making an unnecessary function call. */ /* This is to avoid making an unnecessary function call. */
if (trx->declared_to_be_inside_innodb if (trx->declared_to_be_inside_innodb
@@ -1901,13 +1896,7 @@ innobase_srv_conc_force_exit_innodb(
/*================================*/ /*================================*/
trx_t* trx) /*!< in: transaction handle */ trx_t* trx) /*!< in: transaction handle */
{ {
#ifdef BTR_CUR_HASH_ADAPT ut_ad(!sync_check_iterate(sync_check()));
# ifdef UNIV_DEBUG
btrsea_sync_check check(trx->has_search_latch);
ut_ad(!sync_check_iterate(check));
# endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
/* This is to avoid making an unnecessary function call. */ /* This is to avoid making an unnecessary function call. */
if (trx->declared_to_be_inside_innodb) { if (trx->declared_to_be_inside_innodb) {
@@ -1994,13 +1983,7 @@ const char*
thd_innodb_tmpdir( thd_innodb_tmpdir(
THD* thd) THD* thd)
{ {
#ifdef BTR_CUR_HASH_ADAPT ut_ad(!sync_check_iterate(sync_check()));
# ifdef UNIV_DEBUG
trx_t* trx = thd_to_trx(thd);
btrsea_sync_check check(trx->has_search_latch);
ut_ad(!sync_check_iterate(check));
# endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
const char* tmp_dir = THDVAR(thd, tmpdir); const char* tmp_dir = THDVAR(thd, tmpdir);
@@ -3360,7 +3343,6 @@ innobase_query_caching_of_table_permitted(
return(false); return(false);
} }
trx_assert_no_search_latch(trx);
innobase_srv_conc_force_exit_innodb(trx); innobase_srv_conc_force_exit_innodb(trx);
if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)
@@ -3668,8 +3650,6 @@ ha_innobase::init_table_handle_for_HANDLER(void)
/* Initialize the m_prebuilt struct much like it would be inited in /* Initialize the m_prebuilt struct much like it would be inited in
external_lock */ external_lock */
trx_assert_no_search_latch(m_prebuilt->trx);
innobase_srv_conc_force_exit_innodb(m_prebuilt->trx); innobase_srv_conc_force_exit_innodb(m_prebuilt->trx);
/* If the transaction is not started yet, start it */ /* If the transaction is not started yet, start it */
@@ -4781,12 +4761,6 @@ innobase_commit_ordered(
trx = check_trx_exists(thd); trx = check_trx_exists(thd);
TrxInInnoDB trx_in_innodb(trx); TrxInInnoDB trx_in_innodb(trx);
/* Since we will reserve the kernel mutex, we must not be holding the
search system latch, or we will disobey the latching order. But we
already released it in innobase_xa_prepare() (if not before), so just
have an assert here.*/
trx_assert_no_search_latch(trx);
if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) { if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
/* We cannot throw error here; instead we will catch this error /* We cannot throw error here; instead we will catch this error
again in innobase_commit() and report it from there. */ again in innobase_commit() and report it from there. */
@@ -4998,12 +4972,6 @@ innobase_rollback_trx(
DBUG_ENTER("innobase_rollback_trx"); DBUG_ENTER("innobase_rollback_trx");
DBUG_PRINT("trans", ("aborting transaction")); DBUG_PRINT("trans", ("aborting transaction"));
/* Release a possible FIFO ticket and search latch. Since we will
reserve the trx_sys->mutex, we have to release the search system
latch first to obey the latching order. */
trx_assert_no_search_latch(trx);
innobase_srv_conc_force_exit_innodb(trx); innobase_srv_conc_force_exit_innodb(trx);
/* If we had reserved the auto-inc lock for some table (if /* If we had reserved the auto-inc lock for some table (if
@@ -13101,10 +13069,6 @@ create_table_info_t::initialize()
parent_trx = check_trx_exists(m_thd); parent_trx = check_trx_exists(m_thd);
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
trx_assert_no_search_latch(parent_trx);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@@ -13953,12 +13917,6 @@ innobase_drop_database(
THD* thd = current_thd; THD* thd = current_thd;
/* In case MySQL calls this in the middle of a SELECT
query, release possible adaptive hash latch to avoid
deadlocks of threads */
trx_assert_no_search_latch(check_trx_exists(thd));
ulint len = 0; ulint len = 0;
char* ptr = strend(path) - 2; char* ptr = strend(path) - 2;
@@ -14692,12 +14650,7 @@ ha_innobase::info_low(
update_thd(ha_thd()); update_thd(ha_thd());
/* In case MySQL calls this in the middle of a SELECT query, release m_prebuilt->trx->op_info = "returning various info to MariaDB";
possible adaptive hash latch to avoid deadlocks of threads */
m_prebuilt->trx->op_info = (char*)"returning various info to MariaDB";
trx_assert_no_search_latch(m_prebuilt->trx);
ib_table = m_prebuilt->table; ib_table = m_prebuilt->table;
DBUG_ASSERT(ib_table->n_ref_count > 0); DBUG_ASSERT(ib_table->n_ref_count > 0);
@@ -15544,12 +15497,7 @@ ha_innobase::update_table_comment(
update_thd(ha_thd()); update_thd(ha_thd());
m_prebuilt->trx->op_info = (char*)"returning table comment"; m_prebuilt->trx->op_info = "returning table comment";
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
trx_assert_no_search_latch(m_prebuilt->trx);
#define SSTR( x ) reinterpret_cast< std::ostringstream & >( \ #define SSTR( x ) reinterpret_cast< std::ostringstream & >( \
( std::ostringstream() << std::dec << x ) ).str() ( std::ostringstream() << std::dec << x ) ).str()
@@ -15605,22 +15553,14 @@ ha_innobase::get_foreign_key_create_info(void)
update_thd(ha_thd()); update_thd(ha_thd());
m_prebuilt->trx->op_info = (char*)"getting info on foreign keys"; m_prebuilt->trx->op_info = "getting info on foreign keys";
/* In case MySQL calls this in the middle of a SELECT query,
release possible adaptive hash latch to avoid
deadlocks of threads */
trx_assert_no_search_latch(m_prebuilt->trx);
/* Output the data to a temporary string */ /* Output the data to a temporary string */
std::string str = dict_print_info_on_foreign_keys( std::string str = dict_print_info_on_foreign_keys(
TRUE, m_prebuilt->trx, TRUE, m_prebuilt->trx,
m_prebuilt->table); m_prebuilt->table);
m_prebuilt->trx->op_info = (char*)""; m_prebuilt->trx->op_info = "";
/* Allocate buffer for the string */ /* Allocate buffer for the string */
char* fk_str = (char*) my_malloc(str.length() + 1, MYF(0)); char* fk_str = (char*) my_malloc(str.length() + 1, MYF(0));
@@ -16624,8 +16564,6 @@ innodb_show_status(
trx_t* trx = check_trx_exists(thd); trx_t* trx = check_trx_exists(thd);
trx_assert_no_search_latch(trx);
innobase_srv_conc_force_exit_innodb(trx); innobase_srv_conc_force_exit_innodb(trx);
TrxInInnoDB trx_in_innodb(trx); TrxInInnoDB trx_in_innodb(trx);
@@ -17936,12 +17874,6 @@ innobase_xa_prepare(
thd_get_xid(thd, (MYSQL_XID*) trx->xid); thd_get_xid(thd, (MYSQL_XID*) trx->xid);
/* Release a possible FIFO ticket and search latch. Since we will
reserve the trx_sys->mutex, we have to release the search system
latch first to obey the latching order. */
trx_assert_no_search_latch(trx);
innobase_srv_conc_force_exit_innodb(trx); innobase_srv_conc_force_exit_innodb(trx);
TrxInInnoDB trx_in_innodb(trx); TrxInInnoDB trx_in_innodb(trx);

View File

@@ -3020,11 +3020,6 @@ ha_innopart::records_in_range(
m_prebuilt->trx->op_info = (char*)"estimating records in index range"; m_prebuilt->trx->op_info = (char*)"estimating records in index range";
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads. */
trx_assert_no_search_latch(m_prebuilt->trx);
active_index = keynr; active_index = keynr;
key = table->key_info + active_index; key = table->key_info + active_index;
@@ -3159,11 +3154,6 @@ ha_innopart::estimate_rows_upper_bound()
m_prebuilt->trx->op_info = "calculating upper bound for table rows"; m_prebuilt->trx->op_info = "calculating upper bound for table rows";
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads. */
trx_assert_no_search_latch(m_prebuilt->trx);
for (uint i = m_part_info->get_first_used_partition(); for (uint i = m_part_info->get_first_used_partition();
i < m_tot_parts; i < m_tot_parts;
i = m_part_info->get_next_used_partition(i)) { i = m_part_info->get_next_used_partition(i)) {
@@ -3275,12 +3265,7 @@ ha_innopart::info_low(
update_thd(ha_thd()); update_thd(ha_thd());
/* In case MySQL calls this in the middle of a SELECT query, release m_prebuilt->trx->op_info = "returning various info to MySQL";
possible adaptive hash latch to avoid deadlocks of threads. */
m_prebuilt->trx->op_info = (char*)"returning various info to MySQL";
trx_assert_no_search_latch(m_prebuilt->trx);
ut_ad(m_part_share->get_table_part(0)->n_ref_count > 0); ut_ad(m_part_share->get_table_part(0)->n_ref_count > 0);

View File

@@ -591,7 +591,6 @@ ha_innobase::check_if_supported_inplace_alter(
} }
update_thd(); update_thd();
trx_assert_no_search_latch(m_prebuilt->trx);
/* Change on engine specific table options require rebuild of the /* Change on engine specific table options require rebuild of the
table */ table */

View File

@@ -699,8 +699,7 @@ fill_innodb_trx_from_cache(
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
/* trx_adaptive_hash_latched */ /* trx_adaptive_hash_latched */
OK(fields[IDX_TRX_ADAPTIVE_HASH_LATCHED]->store( OK(fields[IDX_TRX_ADAPTIVE_HASH_LATCHED]->store(0, true));
row->trx_has_search_latch, true));
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
/* trx_is_read_only*/ /* trx_is_read_only*/

View File

@@ -1,6 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@@ -479,11 +480,11 @@ void
log_free_check(void) log_free_check(void)
/*================*/ /*================*/
{ {
#ifdef UNIV_DEBUG
/* During row_log_table_apply(), this function will be called while we /* During row_log_table_apply(), this function will be called while we
are holding some latches. This is OK, as long as we are not holding are holding some latches. This is OK, as long as we are not holding
any latches on buffer blocks. */ any latches on buffer blocks. */
#ifdef UNIV_DEBUG
static const latch_level_t latches[] = { static const latch_level_t latches[] = {
SYNC_DICT, /* dict_sys->mutex during SYNC_DICT, /* dict_sys->mutex during
commit_try_rebuild() */ commit_try_rebuild() */
@@ -491,13 +492,12 @@ log_free_check(void)
commit_try_rebuild() */ commit_try_rebuild() */
SYNC_INDEX_TREE /* index->lock */ SYNC_INDEX_TREE /* index->lock */
}; };
sync_allowed_latches check(
latches, latches + sizeof(latches)/sizeof(*latches));
ut_ad(!sync_check_iterate(check));
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
ut_ad(!sync_check_iterate(
sync_allowed_latches(latches,
latches + UT_ARR_SIZE(latches))));
if (log_sys->check_flush_or_checkpoint) { if (log_sys->check_flush_or_checkpoint) {
log_check_margins(); log_check_margins();

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. Copyright (c) 2017, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -84,10 +84,10 @@ sync_check_find(latch_level_t level);
/** Checks that the level array for the current thread is empty. /** Checks that the level array for the current thread is empty.
Terminate iteration if the functor returns true. Terminate iteration if the functor returns true.
@param[in,out] functor called for each element. @param[in] functor called for each element.
@return true if the functor returns true */ @return true if the functor returns true for any element */
bool bool
sync_check_iterate(sync_check_functor_t& functor); sync_check_iterate(const sync_check_functor_t& functor);
/** Acquires the debug mutex. We cannot use the mutex defined in sync0sync, /** Acquires the debug mutex. We cannot use the mutex defined in sync0sync,
because the debug mutex is also acquired in sync0arr while holding the OS because the debug mutex is also acquired in sync0arr while holding the OS

View File

@@ -1078,108 +1078,43 @@ struct latch_t {
/** Subclass this to iterate over a thread's acquired latch levels. */ /** Subclass this to iterate over a thread's acquired latch levels. */
struct sync_check_functor_t { struct sync_check_functor_t {
virtual ~sync_check_functor_t() { } virtual bool operator()(const latch_level_t) const = 0;
virtual bool operator()(const latch_level_t) = 0;
virtual bool result() const = 0;
}; };
#ifdef BTR_CUR_HASH_ADAPT /** Check that no latch is being held.
/** Functor to check whether the calling thread owns the btr search mutex. */ @tparam some_allowed whether some latches are allowed to be held */
struct btrsea_sync_check : public sync_check_functor_t { template<bool some_allowed = false>
struct sync_checker : public sync_check_functor_t
/** Constructor {
@param[in] has_search_latch true if owns the latch */
explicit btrsea_sync_check(bool has_search_latch)
:
m_result(),
m_has_search_latch(has_search_latch) { }
/** Destructor */
virtual ~btrsea_sync_check() { }
/** Called for every latch owned by the calling thread.
@param[in] level Level of the existing latch
@return true if the predicate check is successful */
virtual bool operator()(const latch_level_t level)
{
/* If calling thread doesn't hold search latch then
check if there are latch level exception provided. */
if (!m_has_search_latch
&& (level != SYNC_SEARCH_SYS
&& level != SYNC_FTS_CACHE)) {
m_result = true;
return(m_result);
}
return(false);
}
/** @return result from the check */
virtual bool result() const
{
return(m_result);
}
private:
/** True if all OK */
bool m_result;
/** If the caller owns the search latch */
const bool m_has_search_latch;
};
#endif /* BTR_CUR_HASH_ADAPT */
/** Functor to check for dictionay latching constraints. */
struct dict_sync_check : public sync_check_functor_t {
/** Constructor
@param[in] dict_mutex_allow true if the dict mutex
is allowed */
explicit dict_sync_check(bool dict_mutex_allowed)
:
m_result(),
m_dict_mutex_allowed(dict_mutex_allowed) { }
/** Destructor */
virtual ~dict_sync_check() { }
/** Check the latching constraints /** Check the latching constraints
@param[in] level The level held by the thread */ @param[in] level The level held by the thread
virtual bool operator()(const latch_level_t level) @return whether a latch violation was detected */
bool operator()(const latch_level_t level) const
{ {
if (!m_dict_mutex_allowed if (some_allowed) {
|| (level != SYNC_DICT switch (level) {
&& level != SYNC_DICT_OPERATION case SYNC_RECV_WRITER:
&& level != SYNC_FTS_CACHE /* This only happens in
/* This only happens in recv_apply_hashed_log_recs. */ recv_apply_hashed_log_recs. */
&& level != SYNC_RECV_WRITER case SYNC_DICT:
&& level != SYNC_NO_ORDER_CHECK)) { case SYNC_DICT_OPERATION:
case SYNC_FTS_CACHE:
m_result = true; case SYNC_NO_ORDER_CHECK:
return(false);
return(true); default:
return(true);
}
} }
return(false); return(true);
} }
/** @return the result of the check */
virtual bool result() const
{
return(m_result);
}
private:
/** True if all OK */
bool m_result;
/** True if it is OK to hold the dict mutex */
const bool m_dict_mutex_allowed;
}; };
/** The strict latch checker (no InnoDB latches may be held) */
typedef struct sync_checker<false> sync_check;
/** The sloppy latch checker (can hold InnoDB dictionary or SQL latches) */
typedef struct sync_checker<true> dict_sync_check;
/** Functor to check for given latching constraints. */ /** Functor to check for given latching constraints. */
struct sync_allowed_latches : public sync_check_functor_t { struct sync_allowed_latches : public sync_check_functor_t {
@@ -1189,9 +1124,7 @@ struct sync_allowed_latches : public sync_check_functor_t {
sync_allowed_latches( sync_allowed_latches(
const latch_level_t* from, const latch_level_t* from,
const latch_level_t* to) const latch_level_t* to)
: : begin(from), end(to) { }
m_result(),
m_latches(from, to) { }
/** Checks whether the given latch_t violates the latch constraint. /** Checks whether the given latch_t violates the latch constraint.
This object maintains a list of allowed latch levels, and if the given This object maintains a list of allowed latch levels, and if the given
@@ -1199,41 +1132,17 @@ struct sync_allowed_latches : public sync_check_functor_t {
then it is a violation. then it is a violation.
@param[in] latch The latch level to check @param[in] latch The latch level to check
@return true if there is a latch ordering violation */ @return true if there is a latch violation */
virtual bool operator()(const latch_level_t level) bool operator()(const latch_level_t level) const
{ {
for (latches_t::const_iterator it = m_latches.begin(); return(std::find(begin, end, level) == end);
it != m_latches.end();
++it) {
if (level == *it) {
m_result = false;
/* No violation */
return(false);
}
}
return(true);
}
/** @return the result of the check */
virtual bool result() const
{
return(m_result);
} }
private: private:
/** Save the result of validation check here /** First element in an array of allowed latch levels */
True if all OK */ const latch_level_t* const begin;
bool m_result; /** First element after the end of the array of allowed latch levels */
const latch_level_t* const end;
typedef std::vector<latch_level_t, ut_allocator<latch_level_t> >
latches_t;
/** List of latch levels that are allowed to be held */
latches_t m_latches;
}; };
/** Get the latch id from a latch name. /** Get the latch id from a latch name.

View File

@@ -1,6 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@@ -162,10 +163,6 @@ struct i_s_trx_row_t {
/*!< check_foreigns in trx_t */ /*!< check_foreigns in trx_t */
const char* trx_foreign_key_error; const char* trx_foreign_key_error;
/*!< detailed_error in trx_t */ /*!< detailed_error in trx_t */
#ifdef BTR_CUR_HASH_ADAPT
ibool trx_has_search_latch;
/*!< has_search_latch in trx_t */
#endif /* BTR_CUR_HASH_ADAPT */
ulint trx_is_read_only; ulint trx_is_read_only;
/*!< trx_t::read_only */ /*!< trx_t::read_only */
ulint trx_is_autocommit_non_locking; ulint trx_is_autocommit_non_locking;

View File

@@ -58,15 +58,6 @@ class FlushObserver;
/** Dummy session used currently in MySQL interface */ /** Dummy session used currently in MySQL interface */
extern sess_t* trx_dummy_sess; extern sess_t* trx_dummy_sess;
#ifdef BTR_CUR_HASH_ADAPT
/** Assert that the transaction is not holding the adaptive hash index latch.
@param[in] trx transaction */
# define trx_assert_no_search_latch(trx) \
ut_ad(!trx->has_search_latch)
#else /* BTR_CUR_HASH_ADAPT */
# define trx_assert_no_search_latch(trx)
#endif
/** Set flush observer for the transaction /** Set flush observer for the transaction
@param[in/out] trx transaction struct @param[in/out] trx transaction struct
@param[in] observer flush observer */ @param[in] observer flush observer */
@@ -1072,11 +1063,6 @@ struct trx_t {
flush the log in flush the log in
trx_commit_complete_for_mysql() */ trx_commit_complete_for_mysql() */
ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */ ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
#ifdef BTR_CUR_HASH_ADAPT
bool has_search_latch;
/*!< TRUE if this trx has latched the
search system latch in S-mode */
#endif /* BTR_CUR_HASH_ADAPT */
trx_dict_op_t dict_operation; /**< @see enum trx_dict_op_t */ trx_dict_op_t dict_operation; /**< @see enum trx_dict_op_t */
/* Fields protected by the srv_conc_mutex. */ /* Fields protected by the srv_conc_mutex. */
@@ -1508,17 +1494,11 @@ private:
} }
/* Avoid excessive mutex acquire/release */ /* Avoid excessive mutex acquire/release */
if (++trx->in_depth > 1) { if (trx->in_depth++) {
/* The transaction is already inside InnoDB. */ /* The transaction is already inside InnoDB. */
ut_ad(trx->in_depth > 1);
return; return;
} }
/* Only the owning thread should release the latch. */
ut_ad(trx->in_depth == 1);
trx_assert_no_search_latch(trx);
trx_mutex_enter(trx); trx_mutex_enter(trx);
wait(trx); wait(trx);
@@ -1543,16 +1523,10 @@ private:
ut_ad(trx->in_depth > 0); ut_ad(trx->in_depth > 0);
if (--trx->in_depth > 0) { if (--trx->in_depth) {
ut_ad(trx->in_depth);
return; return;
} }
/* Only the owning thread should release the latch. */
ut_ad(trx->in_depth == 0);
trx_assert_no_search_latch(trx);
trx_mutex_enter(trx); trx_mutex_enter(trx);
ut_ad((trx->in_innodb & TRX_FORCE_ROLLBACK_MASK) > 0); ut_ad((trx->in_innodb & TRX_FORCE_ROLLBACK_MASK) > 0);

View File

@@ -2231,16 +2231,7 @@ stop_for_a_while:
btr_pcur_store_position(&(plan->pcur), &mtr); btr_pcur_store_position(&(plan->pcur), &mtr);
mtr_commit(&mtr); mtr_commit(&mtr);
ut_ad(!sync_check_iterate(sync_check()));
#ifdef BTR_CUR_HASH_ADAPT
# ifdef UNIV_DEBUG
{
btrsea_sync_check check(true);
ut_ad(!sync_check_iterate(check));
}
# endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
err = DB_SUCCESS; err = DB_SUCCESS;
goto func_exit; goto func_exit;
@@ -2258,14 +2249,7 @@ commit_mtr_for_a_while:
mtr_commit(&mtr); mtr_commit(&mtr);
mtr_has_extra_clust_latch = FALSE; mtr_has_extra_clust_latch = FALSE;
ut_ad(!sync_check_iterate(dict_sync_check()));
#ifdef UNIV_DEBUG
{
dict_sync_check check(true);
ut_ad(!sync_check_iterate(check));
}
#endif /* UNIV_DEBUG */
goto table_loop; goto table_loop;
@@ -2280,20 +2264,13 @@ lock_wait_or_error:
mtr_commit(&mtr); mtr_commit(&mtr);
#ifdef UNIV_DEBUG
{
dict_sync_check check(true);
ut_ad(!sync_check_iterate(check));
}
#endif /* UNIV_DEBUG */
func_exit: func_exit:
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
if (search_latch_locked) { if (search_latch_locked) {
btr_search_s_unlock(index); btr_search_s_unlock(index);
} }
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
ut_ad(!sync_check_iterate(dict_sync_check()));
if (heap != NULL) { if (heap != NULL) {
mem_heap_free(heap); mem_heap_free(heap);
@@ -3041,7 +3018,6 @@ row_sel_store_mysql_field_func(
mem_heap_t* heap; mem_heap_t* heap;
/* Copy an externally stored field to a temporary heap */ /* Copy an externally stored field to a temporary heap */
trx_assert_no_search_latch(prebuilt->trx);
ut_ad(field_no == templ->clust_rec_field_no); ut_ad(field_no == templ->clust_rec_field_no);
ut_ad(templ->type != DATA_POINT); ut_ad(templ->type != DATA_POINT);
@@ -3928,11 +3904,7 @@ row_sel_try_search_shortcut_for_mysql(
ut_ad(!prebuilt->templ_contains_blob); ut_ad(!prebuilt->templ_contains_blob);
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE, btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur, BTR_SEARCH_LEAF, pcur, RW_S_LATCH, mtr);
(trx->has_search_latch)
? RW_S_LATCH
: 0,
mtr);
rec = btr_pcur_get_rec(pcur); rec = btr_pcur_get_rec(pcur);
if (!page_rec_is_user_rec(rec)) { if (!page_rec_is_user_rec(rec)) {
@@ -4189,14 +4161,7 @@ row_search_mvcc(
DBUG_RETURN(DB_END_OF_INDEX); DBUG_RETURN(DB_END_OF_INDEX);
} }
#ifdef BTR_CUR_HASH_ADAPT ut_ad(!sync_check_iterate(sync_check()));
# ifdef UNIV_DEBUG
{
btrsea_sync_check check(trx->has_search_latch);
ut_ad(!sync_check_iterate(check));
}
# endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
if (dict_table_is_discarded(prebuilt->table)) { if (dict_table_is_discarded(prebuilt->table)) {
@@ -4221,8 +4186,6 @@ row_search_mvcc(
&& (prebuilt->read_just_key && (prebuilt->read_just_key
|| prebuilt->m_read_virtual_key); || prebuilt->m_read_virtual_key);
trx_assert_no_search_latch(trx);
/* Reset the new record lock info if srv_locks_unsafe_for_binlog /* Reset the new record lock info if srv_locks_unsafe_for_binlog
is set or session is using a READ COMMITED isolation level. Then is set or session is using a READ COMMITED isolation level. Then
we are able to remove the record locks set here on an individual we are able to remove the record locks set here on an individual
@@ -4377,9 +4340,7 @@ row_search_mvcc(
and if we try that, we can deadlock on the adaptive and if we try that, we can deadlock on the adaptive
hash index semaphore! */ hash index semaphore! */
trx_assert_no_search_latch(trx);
rw_lock_s_lock(btr_get_search_latch(index)); rw_lock_s_lock(btr_get_search_latch(index));
trx->has_search_latch = true;
switch (row_sel_try_search_shortcut_for_mysql( switch (row_sel_try_search_shortcut_for_mysql(
&rec, prebuilt, &offsets, &heap, &rec, prebuilt, &offsets, &heap,
@@ -4434,7 +4395,6 @@ row_search_mvcc(
err = DB_SUCCESS; err = DB_SUCCESS;
rw_lock_s_unlock(btr_get_search_latch(index)); rw_lock_s_unlock(btr_get_search_latch(index));
trx->has_search_latch = false;
goto func_exit; goto func_exit;
@@ -4445,7 +4405,6 @@ row_search_mvcc(
err = DB_RECORD_NOT_FOUND; err = DB_RECORD_NOT_FOUND;
rw_lock_s_unlock(btr_get_search_latch(index)); rw_lock_s_unlock(btr_get_search_latch(index));
trx->has_search_latch = false;
/* NOTE that we do NOT store the cursor /* NOTE that we do NOT store the cursor
position */ position */
@@ -4463,7 +4422,6 @@ row_search_mvcc(
mtr_start(&mtr); mtr_start(&mtr);
rw_lock_s_unlock(btr_get_search_latch(index)); rw_lock_s_unlock(btr_get_search_latch(index));
trx->has_search_latch = false;
} }
} }
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
@@ -4471,8 +4429,6 @@ row_search_mvcc(
/*-------------------------------------------------------------*/ /*-------------------------------------------------------------*/
/* PHASE 3: Open or restore index cursor position */ /* PHASE 3: Open or restore index cursor position */
trx_assert_no_search_latch(trx);
spatial_search = dict_index_is_spatial(index) spatial_search = dict_index_is_spatial(index)
&& mode >= PAGE_CUR_CONTAIN; && mode >= PAGE_CUR_CONTAIN;
@@ -5777,15 +5733,7 @@ func_exit:
} }
} }
#ifdef BTR_CUR_HASH_ADAPT ut_ad(!sync_check_iterate(sync_check()));
# ifdef UNIV_DEBUG
{
btrsea_sync_check check(trx->has_search_latch);
ut_ad(!sync_check_iterate(check));
}
# endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
DEBUG_SYNC_C("innodb_row_search_for_mysql_exit"); DEBUG_SYNC_C("innodb_row_search_for_mysql_exit");

View File

@@ -197,11 +197,6 @@ srv_conc_enter_innodb_with_atomics(
(void) my_atomic_addlint( (void) my_atomic_addlint(
&srv_conc.n_waiting, 1); &srv_conc.n_waiting, 1);
/* Release possible search system latch this
thread has */
trx_assert_no_search_latch(trx);
thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK); thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK);
notified_mysql = TRUE; notified_mysql = TRUE;
@@ -257,15 +252,7 @@ srv_conc_enter_innodb(
{ {
trx_t* trx = prebuilt->trx; trx_t* trx = prebuilt->trx;
#ifdef BTR_CUR_HASH_ADAPT ut_ad(!sync_check_iterate(sync_check()));
# ifdef UNIV_DEBUG
{
btrsea_sync_check check(trx->has_search_latch);
ut_ad(!sync_check_iterate(check));
}
# endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
srv_conc_enter_innodb_with_atomics(trx); srv_conc_enter_innodb_with_atomics(trx);
} }
@@ -279,15 +266,7 @@ srv_conc_force_enter_innodb(
trx_t* trx) /*!< in: transaction object associated with the trx_t* trx) /*!< in: transaction object associated with the
thread */ thread */
{ {
#ifdef BTR_CUR_HASH_ADAPT ut_ad(!sync_check_iterate(sync_check()));
# ifdef UNIV_DEBUG
{
btrsea_sync_check check(trx->has_search_latch);
ut_ad(!sync_check_iterate(check));
}
# endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
if (!srv_thread_concurrency) { if (!srv_thread_concurrency) {
@@ -320,15 +299,7 @@ srv_conc_force_exit_innodb(
srv_conc_exit_innodb_with_atomics(trx); srv_conc_exit_innodb_with_atomics(trx);
#ifdef BTR_CUR_HASH_ADAPT ut_ad(!sync_check_iterate(sync_check()));
# ifdef UNIV_DEBUG
{
btrsea_sync_check check(trx->has_search_latch);
ut_ad(!sync_check_iterate(check));
}
# endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
} }
/*********************************************************************//** /*********************************************************************//**

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. Copyright (c) 2017, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -298,29 +298,23 @@ struct LatchDebug {
} }
/** Iterate over a thread's latches. /** Iterate over a thread's latches.
@param[in,out] functor The callback @param[in] functor The callback
@return true if the functor returns true. */ @return true if the functor returns true. */
bool for_each(sync_check_functor_t& functor) bool for_each(const sync_check_functor_t& functor)
UNIV_NOTHROW UNIV_NOTHROW
{ {
const Latches* latches = thread_latches(); if (const Latches* latches = thread_latches()) {
Latches::const_iterator end = latches->end();
for (Latches::const_iterator it = latches->begin();
it != end; ++it) {
if (latches == 0) { if (functor(it->m_level)) {
return(functor.result()); return(true);
} }
Latches::const_iterator end = latches->end();
for (Latches::const_iterator it = latches->begin();
it != end;
++it) {
if (functor(it->m_level)) {
break;
} }
} }
return(functor.result()); return(false);
} }
/** Removes a latch from the thread level array if it is found there. /** Removes a latch from the thread level array if it is found there.
@@ -1215,13 +1209,12 @@ sync_check_find(latch_level_t level)
/** Iterate over the thread's latches. /** Iterate over the thread's latches.
@param[in,out] functor called for each element. @param[in,out] functor called for each element.
@return false if the sync debug hasn't been initialised @return true if the functor returns true for any element */
@return the value returned by the functor */
bool bool
sync_check_iterate(sync_check_functor_t& functor) sync_check_iterate(const sync_check_functor_t& functor)
{ {
if (LatchDebug::instance() != NULL) { if (LatchDebug* debug = LatchDebug::instance()) {
return(LatchDebug::instance()->for_each(functor)); return(debug->for_each(functor));
} }
return(false); return(false);

View File

@@ -589,10 +589,6 @@ thd_done:
row->trx_foreign_key_error = NULL; row->trx_foreign_key_error = NULL;
} }
#ifdef BTR_CUR_HASH_ADAPT
row->trx_has_search_latch = (ibool) trx->has_search_latch;
#endif /* BTR_CUR_HASH_ADAPT */
row->trx_is_read_only = trx->read_only; row->trx_is_read_only = trx->read_only;
row->trx_is_autocommit_non_locking = trx_is_autocommit_non_locking(trx); row->trx_is_autocommit_non_locking = trx_is_autocommit_non_locking(trx);

View File

@@ -272,8 +272,6 @@ struct TrxFactory {
ut_a(trx->lock.wait_lock == NULL); ut_a(trx->lock.wait_lock == NULL);
ut_a(trx->lock.wait_thr == NULL); ut_a(trx->lock.wait_thr == NULL);
trx_assert_no_search_latch(trx);
ut_a(trx->dict_operation_lock_mode == 0); ut_a(trx->dict_operation_lock_mode == 0);
if (trx->lock.lock_heap != NULL) { if (trx->lock.lock_heap != NULL) {
@@ -341,9 +339,6 @@ struct TrxFactory {
ut_a(trx->lock.wait_thr == NULL); ut_a(trx->lock.wait_thr == NULL);
ut_a(trx->lock.wait_lock == NULL); ut_a(trx->lock.wait_lock == NULL);
trx_assert_no_search_latch(trx);
ut_a(trx->dict_operation_lock_mode == 0); ut_a(trx->dict_operation_lock_mode == 0);
ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0); ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0);
@@ -2413,13 +2408,6 @@ state_ok:
(ulong) n_rec_locks); (ulong) n_rec_locks);
} }
#ifdef BTR_CUR_HASH_ADAPT
if (trx->has_search_latch) {
newline = TRUE;
fputs(", holds adaptive hash latch", f);
}
#endif /* BTR_CUR_HASH_ADAPT */
if (trx->undo_no != 0) { if (trx->undo_no != 0) {
newline = TRUE; newline = TRUE;
fprintf(f, ", undo log entries " TRX_ID_FMT, trx->undo_no); fprintf(f, ", undo log entries " TRX_ID_FMT, trx->undo_no);
@@ -2551,11 +2539,6 @@ state_ok:
fprintf(f, "que state %lu ", (ulong) trx->lock.que_state); fprintf(f, "que state %lu ", (ulong) trx->lock.que_state);
} }
if (trx->has_search_latch) {
newline = TRUE;
fputs(", holds adaptive hash latch", f);
}
if (trx->undo_no != 0) { if (trx->undo_no != 0) {
newline = TRUE; newline = TRUE;
fprintf(f, ", undo log entries " TRX_ID_FMT, trx->undo_no); fprintf(f, ", undo log entries " TRX_ID_FMT, trx->undo_no);