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; 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(&tempfile);
my_b_clear(&buffpek_pointers); my_b_clear(&buffpek_pointers);
buffpek=0; 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 Check if all storage engines used in transaction agree that after
rollback to savepoint it is safe to release MDL locks acquired 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, enum_binlog_command binlog_command,
const char *query, uint query_length, const char *query, uint query_length,
const char *db, const char *table_name); const char *db, const char *table_name);
int (*release_temporary_latches)(handlerton *hton, THD *thd);
/* /*
Get log status. 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_repartition_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_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 */ /* transactions: interface to handlerton functions */
int ha_start_consistent_snapshot(THD *thd); int ha_start_consistent_snapshot(THD *thd);
int ha_commit_or_rollback_by_xid(XID *xid, bool commit); 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) 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 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 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.in_trans,
(int)flags.autocommit)); (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 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 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) if (thd->killed == ABORT_QUERY)
DBUG_RETURN(FALSE); 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(); protocol->prepare_for_resend();
if (protocol->send_result_set_row(&items)) if (protocol->send_result_set_row(&items))
{ {
@ -2776,13 +2769,6 @@ int select_send::send_data(List<Item> &items)
bool select_send::send_eof() 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 Don't send EOF if we're in error condition (which implies we've already
sent or are sending an error) sent or are sending an error)

View File

@ -1,6 +1,6 @@
/* /*
Copyright (c) 2000, 2016, Oracle and/or its affiliates. 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 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 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); error= write_record(thd, table, &info);
table->auto_increment_field_not_null= FALSE; table->auto_increment_field_not_null= FALSE;

View File

@ -2035,28 +2035,6 @@ thd_to_trx_id(
} }
#endif /* WITH_WSREP */ #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 Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
time calls srv_active_wake_master_thread. This function should be used time calls srv_active_wake_master_thread. This function should be used
@ -3911,9 +3889,6 @@ innobase_init(
innobase_hton->flags = innobase_hton->flags =
HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS; HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS;
innobase_hton->release_temporary_latches =
innobase_release_temporary_latches;
#ifdef MYSQL_REPLACE_TRX_IN_THD #ifdef MYSQL_REPLACE_TRX_IN_THD
innobase_hton->replace_native_transaction_in_thd = innobase_hton->replace_native_transaction_in_thd =
innodb_replace_trx_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); dict_table_autoinc_unlock(table);
} }
/*****************************************************************//** /** Open an InnoDB table
Creates and opens a handle to a table which already exists in an InnoDB @param[in] name table name
database. @return error code
@return 1 if error, 0 if success */ @retval 0 on success */
int int
ha_innobase::open( ha_innobase::open(const char* name, int, uint)
/*==============*/
const char* name, /*!< in: table name */
int mode, /*!< in: not used */
uint test_if_locked) /*!< in: not used */
{ {
dict_table_t* ib_table; dict_table_t* ib_table;
char norm_name[FN_REFLEN]; char norm_name[FN_REFLEN];
THD* thd;
dict_err_ignore_t ignore_err = DICT_ERR_IGNORE_NONE; dict_err_ignore_t ignore_err = DICT_ERR_IGNORE_NONE;
DBUG_ENTER("ha_innobase::open"); 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); normalize_table_name(norm_name, name);
m_user_thd = NULL; m_user_thd = NULL;
@ -6583,6 +6540,7 @@ ha_innobase::open(
m_upd_buf_size = 0; m_upd_buf_size = 0;
char* is_part = is_partition(norm_name); char* is_part = is_partition(norm_name);
THD* thd = ha_thd();
/* Check whether FOREIGN_KEY_CHECKS is set to 0. If so, the table /* 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 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"); DBUG_ENTER("ha_innobase::close");
THD* thd = ha_thd();
if (thd != NULL) {
innobase_release_temporary_latches(ht, thd);
}
row_prebuilt_free(m_prebuilt, FALSE); row_prebuilt_free(m_prebuilt, FALSE);
if (m_upd_buf != NULL) { if (m_upd_buf != NULL) {

View File

@ -906,18 +906,6 @@ innodb_base_col_setup_for_stored(
/** whether this is a computed virtual column */ /** whether this is a computed virtual column */
#define innobase_is_v_fld(field) ((field)->vcol_info && !(field)->stored_in_db()) #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 */ /** Always normalize table name to lower case on Windows */
#ifdef _WIN32 #ifdef _WIN32
#define normalize_table_name(norm_name, name) \ #define normalize_table_name(norm_name, name) \

View File

@ -932,7 +932,6 @@ ha_innopart::open(
{ {
dict_table_t* ib_table; dict_table_t* ib_table;
char norm_name[FN_REFLEN]; char norm_name[FN_REFLEN];
THD* thd;
DBUG_ENTER("ha_innopart::open"); DBUG_ENTER("ha_innopart::open");
@ -942,16 +941,11 @@ ha_innopart::open(
ut_ad(table->part_info != NULL); ut_ad(table->part_info != NULL);
m_part_info = table->part_info; m_part_info = table->part_info;
} }
thd = ha_thd();
/* Under some cases MySQL seems to call this function while /* Under some cases MySQL seems to call this function while
holding search latch(es). This breaks the latching order as holding search latch(es). This breaks the latching order as
we acquire dict_sys->mutex below and leads to a deadlock. */ 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); normalize_table_name(norm_name, name);
m_user_thd = NULL; m_user_thd = NULL;
@ -1017,6 +1011,7 @@ share_error:
MONITOR_INC(MONITOR_TABLE_OPEN); MONITOR_INC(MONITOR_TABLE_OPEN);
bool no_tablespace; bool no_tablespace;
THD* thd = ha_thd();
/* TODO: Should we do this check for every partition during ::open()? */ /* TODO: Should we do this check for every partition during ::open()? */
/* TODO: refactor this in ha_innobase so it can increase code reuse. */ /* TODO: refactor this in ha_innobase so it can increase code reuse. */
@ -1372,15 +1367,8 @@ void ha_innopart::clear_ins_upd_nodes()
int int
ha_innopart::close() ha_innopart::close()
{ {
THD* thd;
DBUG_ENTER("ha_innopart::close"); 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_pcur_parts == NULL);
ut_ad(m_clust_pcur_parts == NULL); ut_ad(m_clust_pcur_parts == NULL);
close_partitioning(); 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; share->state.dupp_key= MI_MAX_KEY;
strmov(fixed_name,file->filename); 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 Don't lock tables if we have used LOCK TABLE or if we come from
enable_index() enable_index()

View File

@ -2122,39 +2122,6 @@ ha_innobase::is_fake_change_enabled(THD* thd)
return(trx && UNIV_UNLIKELY(trx->fake_changes)); 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 Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
time calls srv_active_wake_master_thread. This function should be used 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 | innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS |
HTON_SUPPORTS_FOREIGN_KEYS; HTON_SUPPORTS_FOREIGN_KEYS;
innobase_hton->release_temporary_latches =
innobase_release_temporary_latches;
innobase_hton->kill_query = innobase_kill_connection; innobase_hton->kill_query = innobase_kill_connection;
if (srv_file_per_table) if (srv_file_per_table)
@ -6262,9 +6226,6 @@ ha_innobase::open(
thd = ha_thd(); thd = ha_thd();
/* No-op in XtraDB */
innobase_release_temporary_latches(ht, thd);
normalize_table_name(norm_name, name); normalize_table_name(norm_name, name);
user_thd = NULL; user_thd = NULL;
@ -6724,9 +6685,6 @@ ha_innobase::close()
thd = ha_thd(); thd = ha_thd();
/* No-op in XtraDB */
innobase_release_temporary_latches(ht, thd);
row_prebuilt_free(prebuilt, FALSE); row_prebuilt_free(prebuilt, FALSE);
if (upd_buf != NULL) { if (upd_buf != NULL) {