Remove the unnecessary method handlerton::release_temporary_latches()

The sole purpose of handlerton::release_temporary_latches and its wrapper
function was to release the InnoDB adaptive hash index latch
(btr_search_latch).

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. As part of that,
the function trx_search_latch_release_if_reserved() was changed to an
assertion and the function trx_reserve_search_latch_if_not_reserved()
was removed, and handlerton::release_temporary_latches() practically
became a no-op.

Note: MDEV-12121 replaced the function
trx_search_latch_release_if_reserved()
with the more appropriately named macro trx_assert_no_search_latch().
This commit is contained in:
Marko Mäkelä 2017-06-16 11:05:09 +03:00
parent 6b71b3e348
commit e5980bf1b1
11 changed files with 9 additions and 197 deletions

View File

@ -182,12 +182,6 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
outfile= &sort->io_cache;
/*
Release InnoDB's adaptive hash index latch (if holding) before
running a sort.
*/
ha_release_temporary_latches(thd);
my_b_clear(&tempfile);
my_b_clear(&buffpek_pointers);
buffpek=0;

View File

@ -2015,44 +2015,6 @@ commit_checkpoint_notify_ha(handlerton *hton, void *cookie)
}
/**
@details
This function should be called when MySQL sends rows of a SELECT result set
or the EOF mark to the client. It releases a possible adaptive hash index
S-latch held by thd in InnoDB and also releases a possible InnoDB query
FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
keep them over several calls of the InnoDB handler interface when a join
is executed. But when we let the control to pass to the client they have
to be released because if the application program uses mysql_use_result(),
it may deadlock on the S-latch if the application on another connection
performs another SQL query. In MySQL-4.1 this is even more important because
there a connection can have several SELECT queries open at the same time.
@param thd the thread handle of the current connection
@return
always 0
*/
int ha_release_temporary_latches(THD *thd)
{
Ha_trx_info *info;
/*
Note that below we assume that only transactional storage engines
may need release_temporary_latches(). If this will ever become false,
we could iterate on thd->open_tables instead (and remove duplicates
as if (!seen[hton->slot]) { seen[hton->slot]=1; ... }).
*/
for (info= thd->transaction.stmt.ha_list; info; info= info->next())
{
handlerton *hton= info->ht();
if (hton && hton->release_temporary_latches)
hton->release_temporary_latches(hton, thd);
}
return 0;
}
/**
Check if all storage engines used in transaction agree that after
rollback to savepoint it is safe to release MDL locks acquired after

View File

@ -1211,7 +1211,6 @@ struct handlerton
enum_binlog_command binlog_command,
const char *query, uint query_length,
const char *db, const char *table_name);
int (*release_temporary_latches)(handlerton *hton, THD *thd);
/*
Get log status.
@ -4282,9 +4281,6 @@ int ha_change_key_cache_param(KEY_CACHE *key_cache);
int ha_repartition_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
/* report to InnoDB that control passes to the client */
int ha_release_temporary_latches(THD *thd);
/* transactions: interface to handlerton functions */
int ha_start_consistent_snapshot(THD *thd);
int ha_commit_or_rollback_by_xid(XID *xid, bool commit);

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2010, 2013, Monty Program Ab
Copyright (c) 2010, 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
@ -1465,12 +1465,6 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
(int)flags.in_trans,
(int)flags.autocommit));
/*
Make InnoDB to release the adaptive hash index latch before
acquiring the query cache mutex.
*/
ha_release_temporary_latches(thd);
/*
A table- or a full flush operation can potentially take a long time to
finish. We choose not to wait for them and skip caching statements

View File

@ -2751,13 +2751,6 @@ int select_send::send_data(List<Item> &items)
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(FALSE);
/*
We may be passing the control from mysqld to the client: release the
InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
by thd
*/
ha_release_temporary_latches(thd);
protocol->prepare_for_resend();
if (protocol->send_result_set_row(&items))
{
@ -2776,13 +2769,6 @@ int select_send::send_data(List<Item> &items)
bool select_send::send_eof()
{
/*
We may be passing the control from mysqld to the client: release the
InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
by thd
*/
ha_release_temporary_latches(thd);
/*
Don't send EOF if we're in error condition (which implies we've already
sent or are sending an error)

View File

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
Copyright (c) 2010, 2017, MariaDB
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
@ -3751,9 +3751,6 @@ int select_insert::send_data(List<Item> &values)
}
}
// Release latches in case bulk insert takes a long time
ha_release_temporary_latches(thd);
error= write_record(thd, table, &info);
table->auto_increment_field_not_null= FALSE;

View File

@ -2035,28 +2035,6 @@ thd_to_trx_id(
}
#endif /* WITH_WSREP */
/********************************************************************//**
Call this function when mysqld passes control to the client. That is to
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
documentation, see handler.cc.
@return 0 */
inline
int
innobase_release_temporary_latches(
/*===============================*/
handlerton* hton, /*!< in: handlerton */
THD* thd) /*!< in: MySQL thread */
{
DBUG_ASSERT(hton == innodb_hton_ptr);
if (!srv_was_started) {
} else if (trx_t* trx = thd_to_trx(thd)) {
trx_assert_no_search_latch(trx);
}
return(0);
}
/********************************************************************//**
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
time calls srv_active_wake_master_thread. This function should be used
@ -3911,9 +3889,6 @@ innobase_init(
innobase_hton->flags =
HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS;
innobase_hton->release_temporary_latches =
innobase_release_temporary_latches;
#ifdef MYSQL_REPLACE_TRX_IN_THD
innobase_hton->replace_native_transaction_in_thd =
innodb_replace_trx_in_thd;
@ -6538,37 +6513,19 @@ initialize_auto_increment(dict_table_t* table, const Field* field)
dict_table_autoinc_unlock(table);
}
/*****************************************************************//**
Creates and opens a handle to a table which already exists in an InnoDB
database.
@return 1 if error, 0 if success */
/** Open an InnoDB table
@param[in] name table name
@return error code
@retval 0 on success */
int
ha_innobase::open(
/*==============*/
const char* name, /*!< in: table name */
int mode, /*!< in: not used */
uint test_if_locked) /*!< in: not used */
ha_innobase::open(const char* name, int, uint)
{
dict_table_t* ib_table;
char norm_name[FN_REFLEN];
THD* thd;
dict_err_ignore_t ignore_err = DICT_ERR_IGNORE_NONE;
DBUG_ENTER("ha_innobase::open");
UT_NOT_USED(mode);
UT_NOT_USED(test_if_locked);
thd = ha_thd();
/* Under some cases MySQL seems to call this function while
holding search latch(es). This breaks the latching order as
we acquire dict_sys->mutex below and leads to a deadlock. */
if (thd != NULL) {
innobase_release_temporary_latches(ht, thd);
}
normalize_table_name(norm_name, name);
m_user_thd = NULL;
@ -6583,6 +6540,7 @@ ha_innobase::open(
m_upd_buf_size = 0;
char* is_part = is_partition(norm_name);
THD* thd = ha_thd();
/* Check whether FOREIGN_KEY_CHECKS is set to 0. If so, the table
can be opened even if some FK indexes are missing. If not, the table
@ -7053,12 +7011,6 @@ ha_innobase::close()
{
DBUG_ENTER("ha_innobase::close");
THD* thd = ha_thd();
if (thd != NULL) {
innobase_release_temporary_latches(ht, thd);
}
row_prebuilt_free(m_prebuilt, FALSE);
if (m_upd_buf != NULL) {

View File

@ -906,18 +906,6 @@ innodb_base_col_setup_for_stored(
/** whether this is a computed virtual column */
#define innobase_is_v_fld(field) ((field)->vcol_info && !(field)->stored_in_db())
/** Release temporary latches.
Call this function when mysqld passes control to the client. That is to
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
documentation, see handler.cc.
@param[in] hton Handlerton.
@param[in] thd MySQL thread.
@return 0 */
int
innobase_release_temporary_latches(
handlerton* hton,
THD* thd);
/** Always normalize table name to lower case on Windows */
#ifdef _WIN32
#define normalize_table_name(norm_name, name) \

View File

@ -932,7 +932,6 @@ ha_innopart::open(
{
dict_table_t* ib_table;
char norm_name[FN_REFLEN];
THD* thd;
DBUG_ENTER("ha_innopart::open");
@ -942,16 +941,11 @@ ha_innopart::open(
ut_ad(table->part_info != NULL);
m_part_info = table->part_info;
}
thd = ha_thd();
/* Under some cases MySQL seems to call this function while
holding search latch(es). This breaks the latching order as
we acquire dict_sys->mutex below and leads to a deadlock. */
if (thd != NULL) {
innobase_release_temporary_latches(ht, thd);
}
normalize_table_name(norm_name, name);
m_user_thd = NULL;
@ -1017,6 +1011,7 @@ share_error:
MONITOR_INC(MONITOR_TABLE_OPEN);
bool no_tablespace;
THD* thd = ha_thd();
/* TODO: Should we do this check for every partition during ::open()? */
/* TODO: refactor this in ha_innobase so it can increase code reuse. */
@ -1372,15 +1367,8 @@ void ha_innopart::clear_ins_upd_nodes()
int
ha_innopart::close()
{
THD* thd;
DBUG_ENTER("ha_innopart::close");
thd = ha_thd();
if (thd != NULL) {
innobase_release_temporary_latches(ht, thd);
}
ut_ad(m_pcur_parts == NULL);
ut_ad(m_clust_pcur_parts == NULL);
close_partitioning();

View File

@ -1182,9 +1182,6 @@ int ha_myisam::repair(THD *thd, HA_CHECK &param, bool do_optimize)
share->state.dupp_key= MI_MAX_KEY;
strmov(fixed_name,file->filename);
// Release latches since this can take a long time
ha_release_temporary_latches(thd);
/*
Don't lock tables if we have used LOCK TABLE or if we come from
enable_index()

View File

@ -2122,39 +2122,6 @@ ha_innobase::is_fake_change_enabled(THD* thd)
return(trx && UNIV_UNLIKELY(trx->fake_changes));
}
/********************************************************************//**
In XtraDB it is impossible for a transaction to own a search latch outside of
InnoDB code, so there is nothing to release on demand. We keep this function to
simplify maintenance.
@return 0 */
static
int
innobase_release_temporary_latches(
/*===============================*/
handlerton* hton MY_ATTRIBUTE((unused)), /*!< in: handlerton */
THD* thd MY_ATTRIBUTE((unused))) /*!< in: MySQL thread */
{
#ifdef UNIV_DEBUG
DBUG_ASSERT(hton == innodb_hton_ptr);
if (!innodb_inited || thd == NULL) {
return(0);
}
trx_t* trx = thd_to_trx(thd);
if (trx != NULL) {
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
#endif
trx_search_latch_release_if_reserved(trx);
}
#endif
return(0);
}
/********************************************************************//**
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
time calls srv_active_wake_master_thread. This function should be used
@ -3813,9 +3780,6 @@ innobase_init(
innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS |
HTON_SUPPORTS_FOREIGN_KEYS;
innobase_hton->release_temporary_latches =
innobase_release_temporary_latches;
innobase_hton->kill_query = innobase_kill_connection;
if (srv_file_per_table)
@ -6262,9 +6226,6 @@ ha_innobase::open(
thd = ha_thd();
/* No-op in XtraDB */
innobase_release_temporary_latches(ht, thd);
normalize_table_name(norm_name, name);
user_thd = NULL;
@ -6724,9 +6685,6 @@ ha_innobase::close()
thd = ha_thd();
/* No-op in XtraDB */
innobase_release_temporary_latches(ht, thd);
row_prebuilt_free(prebuilt, FALSE);
if (upd_buf != NULL) {