Skip to content
Permalink
Browse files
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.
  • Loading branch information
dr-m committed Jun 16, 2017
1 parent e5980bf commit 50faeda
Show file tree
Hide file tree
Showing 17 changed files with 89 additions and 420 deletions.
@@ -1,6 +1,7 @@
/*****************************************************************************
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
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);
}

#ifdef UNIV_DEBUG
dict_sync_check check(true);

ut_ad(!sync_check_iterate(check));
#endif /* UNIV_DEBUG */
ut_ad(!sync_check_iterate(dict_sync_check()));

ut_ad(err != DB_SUCCESS || btr_validate_index(m_index, NULL, false));
return(err);
@@ -1870,15 +1870,8 @@ buf_flush_batch(
counts */
{
ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);

#ifdef UNIV_DEBUG
{
dict_sync_check check(true);

ut_ad(flush_type != BUF_FLUSH_LIST
|| !sync_check_iterate(check));
}
#endif /* UNIV_DEBUG */
ut_ad(flush_type == BUF_FLUSH_LRU
|| !sync_check_iterate(dict_sync_check()));

buf_pool_mutex_enter(buf_pool);

@@ -6113,14 +6113,7 @@ dict_set_corrupted(
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_indexes));

#ifdef UNIV_DEBUG
{
dict_sync_check check(true);

ut_ad(!sync_check_iterate(check));
}
#endif /* UNIV_DEBUG */
ut_ad(!sync_check_iterate(dict_sync_check()));

/* Mark the table as corrupted only if the clustered index
is corrupted */
@@ -1869,6 +1869,8 @@ void
innobase_srv_conc_exit_innodb(
row_prebuilt_t* prebuilt)
{
ut_ad(!sync_check_iterate(sync_check()));

#ifdef WITH_WSREP
if (wsrep_on(prebuilt->trx->mysql_thd) &&
wsrep_thd_is_BF(prebuilt->trx->mysql_thd, FALSE)) {
@@ -1877,13 +1879,6 @@ innobase_srv_conc_exit_innodb(
#endif /* WITH_WSREP */

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. */
if (trx->declared_to_be_inside_innodb
@@ -1901,13 +1896,7 @@ innobase_srv_conc_force_exit_innodb(
/*================================*/
trx_t* trx) /*!< in: transaction handle */
{
#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 */
ut_ad(!sync_check_iterate(sync_check()));

/* This is to avoid making an unnecessary function call. */
if (trx->declared_to_be_inside_innodb) {
@@ -1994,13 +1983,7 @@ const char*
thd_innodb_tmpdir(
THD* thd)
{
#ifdef BTR_CUR_HASH_ADAPT
# 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 */
ut_ad(!sync_check_iterate(sync_check()));

const char* tmp_dir = THDVAR(thd, tmpdir);

@@ -3360,7 +3343,6 @@ innobase_query_caching_of_table_permitted(
return(false);
}

trx_assert_no_search_latch(trx);
innobase_srv_conc_force_exit_innodb(trx);

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
external_lock */

trx_assert_no_search_latch(m_prebuilt->trx);

innobase_srv_conc_force_exit_innodb(m_prebuilt->trx);

/* If the transaction is not started yet, start it */
@@ -4781,12 +4761,6 @@ innobase_commit_ordered(
trx = check_trx_exists(thd);
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)) {
/* We cannot throw error here; instead we will catch this error
again in innobase_commit() and report it from there. */
@@ -4998,12 +4972,6 @@ innobase_rollback_trx(
DBUG_ENTER("innobase_rollback_trx");
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);

/* 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);

/* 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);
}

@@ -13953,12 +13917,6 @@ innobase_drop_database(

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;
char* ptr = strend(path) - 2;

@@ -14692,12 +14650,7 @@ ha_innobase::info_low(

update_thd(ha_thd());

/* In case MySQL calls this in the middle of a SELECT query, release
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);
m_prebuilt->trx->op_info = "returning various info to MariaDB";

ib_table = m_prebuilt->table;
DBUG_ASSERT(ib_table->n_ref_count > 0);
@@ -15544,12 +15497,7 @@ ha_innobase::update_table_comment(

update_thd(ha_thd());

m_prebuilt->trx->op_info = (char*)"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);
m_prebuilt->trx->op_info = "returning table comment";

#define SSTR( x ) reinterpret_cast< std::ostringstream & >( \
( std::ostringstream() << std::dec << x ) ).str()
@@ -15605,22 +15553,14 @@ ha_innobase::get_foreign_key_create_info(void)

update_thd(ha_thd());

m_prebuilt->trx->op_info = (char*)"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);


m_prebuilt->trx->op_info = "getting info on foreign keys";

/* Output the data to a temporary string */
std::string str = dict_print_info_on_foreign_keys(
TRUE, m_prebuilt->trx,
m_prebuilt->table);

m_prebuilt->trx->op_info = (char*)"";
m_prebuilt->trx->op_info = "";

/* Allocate buffer for the string */
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_assert_no_search_latch(trx);

innobase_srv_conc_force_exit_innodb(trx);

TrxInInnoDB trx_in_innodb(trx);
@@ -17936,12 +17874,6 @@ innobase_xa_prepare(

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);

TrxInInnoDB trx_in_innodb(trx);
@@ -3020,11 +3020,6 @@ ha_innopart::records_in_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;

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";

/* 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();
i < m_tot_parts;
i = m_part_info->get_next_used_partition(i)) {
@@ -3275,12 +3265,7 @@ ha_innopart::info_low(

update_thd(ha_thd());

/* In case MySQL calls this in the middle of a SELECT query, release
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);
m_prebuilt->trx->op_info = "returning various info to MySQL";

ut_ad(m_part_share->get_table_part(0)->n_ref_count > 0);

@@ -591,7 +591,6 @@ ha_innobase::check_if_supported_inplace_alter(
}

update_thd();
trx_assert_no_search_latch(m_prebuilt->trx);

/* Change on engine specific table options require rebuild of the
table */
@@ -699,8 +699,7 @@ fill_innodb_trx_from_cache(

#ifdef BTR_CUR_HASH_ADAPT
/* trx_adaptive_hash_latched */
OK(fields[IDX_TRX_ADAPTIVE_HASH_LATCHED]->store(
row->trx_has_search_latch, true));
OK(fields[IDX_TRX_ADAPTIVE_HASH_LATCHED]->store(0, true));
#endif /* BTR_CUR_HASH_ADAPT */

/* trx_is_read_only*/
@@ -1,6 +1,7 @@
/*****************************************************************************

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
the terms of the GNU General Public License as published by the Free Software
@@ -479,25 +480,24 @@ void
log_free_check(void)
/*================*/
{
#ifdef UNIV_DEBUG
/* 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
any latches on buffer blocks. */

#ifdef UNIV_DEBUG
static const latch_level_t latches[] = {
SYNC_DICT, /* dict_sys->mutex during
commit_try_rebuild() */
SYNC_DICT_OPERATION, /* dict_operation_lock X-latch during
commit_try_rebuild() */
SYNC_INDEX_TREE /* index->lock */
};

sync_allowed_latches check(
latches, latches + sizeof(latches)/sizeof(*latches));

ut_ad(!sync_check_iterate(check));
#endif /* UNIV_DEBUG */

ut_ad(!sync_check_iterate(
sync_allowed_latches(latches,
latches + UT_ARR_SIZE(latches))));

if (log_sys->check_flush_or_checkpoint) {

log_check_margins();
@@ -1,7 +1,7 @@
/*****************************************************************************

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
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.
Terminate iteration if the functor returns true.
@param[in,out] functor called for each element.
@return true if the functor returns true */
@param[in] functor called for each element.
@return true if the functor returns true for any element */
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,
because the debug mutex is also acquired in sync0arr while holding the OS

0 comments on commit 50faeda

Please sign in to comment.