mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
ha_innodb.cc:
Fix a possible hang at the adaptive hash index latch if MySQL does query estimations also in the middle of a SELECT statement processing
This commit is contained in:
132
sql/ha_innodb.cc
132
sql/ha_innodb.cc
@ -2994,6 +2994,7 @@ ha_innobase::create(
|
||||
{
|
||||
int error;
|
||||
dict_table_t* innobase_table;
|
||||
trx_t* parent_trx;
|
||||
trx_t* trx;
|
||||
int primary_key_no;
|
||||
uint i;
|
||||
@ -3005,6 +3006,16 @@ ha_innobase::create(
|
||||
|
||||
DBUG_ASSERT(thd != NULL);
|
||||
|
||||
/* Get the transaction associated with the current thd, or create one
|
||||
if not yet created */
|
||||
|
||||
parent_trx = check_trx_exists(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_search_latch_release_if_reserved(parent_trx);
|
||||
|
||||
trx = trx_allocate_for_mysql();
|
||||
|
||||
if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
|
||||
@ -3165,11 +3176,22 @@ ha_innobase::delete_table(
|
||||
{
|
||||
ulint name_len;
|
||||
int error;
|
||||
trx_t* parent_trx;
|
||||
trx_t* trx;
|
||||
char norm_name[1000];
|
||||
|
||||
DBUG_ENTER("ha_innobase::delete_table");
|
||||
|
||||
/* Get the transaction associated with the current thd, or create one
|
||||
if not yet created */
|
||||
|
||||
parent_trx = check_trx_exists(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_search_latch_release_if_reserved(parent_trx);
|
||||
|
||||
if (lower_case_table_names) {
|
||||
srv_lower_case_table_names = TRUE;
|
||||
} else {
|
||||
@ -3224,11 +3246,22 @@ innobase_drop_database(
|
||||
the database name is 'test' */
|
||||
{
|
||||
ulint len = 0;
|
||||
trx_t* parent_trx;
|
||||
trx_t* trx;
|
||||
char* ptr;
|
||||
int error;
|
||||
char namebuf[10000];
|
||||
|
||||
/* Get the transaction associated with the current thd, or create one
|
||||
if not yet created */
|
||||
|
||||
parent_trx = check_trx_exists(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_search_latch_release_if_reserved(parent_trx);
|
||||
|
||||
ptr = strend(path) - 2;
|
||||
|
||||
while (ptr >= path && *ptr != '\\' && *ptr != '/') {
|
||||
@ -3280,12 +3313,23 @@ ha_innobase::rename_table(
|
||||
ulint name_len1;
|
||||
ulint name_len2;
|
||||
int error;
|
||||
trx_t* parent_trx;
|
||||
trx_t* trx;
|
||||
char norm_from[1000];
|
||||
char norm_to[1000];
|
||||
|
||||
DBUG_ENTER("ha_innobase::rename_table");
|
||||
|
||||
/* Get the transaction associated with the current thd, or create one
|
||||
if not yet created */
|
||||
|
||||
parent_trx = check_trx_exists(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_search_latch_release_if_reserved(parent_trx);
|
||||
|
||||
if (lower_case_table_names) {
|
||||
srv_lower_case_table_names = TRUE;
|
||||
} else {
|
||||
@ -3332,8 +3376,8 @@ Estimates the number of index records in a range. */
|
||||
ha_rows
|
||||
ha_innobase::records_in_range(
|
||||
/*==========================*/
|
||||
/* out: estimated number of rows,
|
||||
currently 32-bit int or uint */
|
||||
/* out: estimated number of
|
||||
rows */
|
||||
int keynr, /* in: index number */
|
||||
const mysql_byte* start_key, /* in: start key value of the
|
||||
range, may also be empty */
|
||||
@ -3364,9 +3408,16 @@ ha_innobase::records_in_range(
|
||||
|
||||
DBUG_ENTER("records_in_range");
|
||||
|
||||
/* Warning: since it is not sure that MySQL calls external_lock
|
||||
before calling this function, the trx field in prebuilt can be
|
||||
obsolete! */
|
||||
/* We do not know if MySQL can call this function before calling
|
||||
external_lock(). To be safe, update the thd of the current table
|
||||
handle. */
|
||||
|
||||
update_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_search_latch_release_if_reserved(prebuilt->trx);
|
||||
|
||||
active_index = keynr;
|
||||
|
||||
@ -3420,12 +3471,19 @@ ha_innobase::estimate_number_of_rows(void)
|
||||
ulonglong estimate;
|
||||
ulonglong local_data_file_length;
|
||||
|
||||
/* Warning: since it is not sure that MySQL calls external_lock
|
||||
before calling this function, the trx field in prebuilt can be
|
||||
obsolete! */
|
||||
|
||||
DBUG_ENTER("info");
|
||||
|
||||
/* We do not know if MySQL can call this function before calling
|
||||
external_lock(). To be safe, update the thd of the current table
|
||||
handle. */
|
||||
|
||||
update_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_search_latch_release_if_reserved(prebuilt->trx);
|
||||
|
||||
index = dict_table_get_first_index_noninline(prebuilt->table);
|
||||
|
||||
local_data_file_length = ((ulonglong) index->stat_n_leaf_pages)
|
||||
@ -3489,9 +3547,16 @@ ha_innobase::info(
|
||||
return;
|
||||
}
|
||||
|
||||
/* Warning: since it is not sure that MySQL calls external_lock
|
||||
before calling this function, the trx field in prebuilt can be
|
||||
obsolete! */
|
||||
/* We do not know if MySQL can call this function before calling
|
||||
external_lock(). To be safe, update the thd of the current table
|
||||
handle. */
|
||||
|
||||
update_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_search_latch_release_if_reserved(prebuilt->trx);
|
||||
|
||||
ib_table = prebuilt->table;
|
||||
|
||||
@ -3559,12 +3624,6 @@ ha_innobase::info(
|
||||
}
|
||||
}
|
||||
|
||||
/* The trx struct in InnoDB contains a pthread mutex embedded:
|
||||
in the debug version of MySQL that it replaced by a 'safe mutex'
|
||||
which is of a different size. We have to use a function to access
|
||||
trx fields. Otherwise trx->error_info will be a random
|
||||
pointer and cause a seg fault. */
|
||||
|
||||
if (flag & HA_STATUS_ERRKEY) {
|
||||
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
|
||||
|
||||
@ -3630,9 +3689,16 @@ ha_innobase::update_table_comment(
|
||||
char* str = my_malloc(length + 16500, MYF(0));
|
||||
char* pos;
|
||||
|
||||
/* Warning: since it is not sure that MySQL calls external_lock
|
||||
before calling this function, the trx field in prebuilt can be
|
||||
obsolete! */
|
||||
/* We do not know if MySQL can call this function before calling
|
||||
external_lock(). To be safe, update the thd of the current table
|
||||
handle. */
|
||||
|
||||
update_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_search_latch_release_if_reserved(prebuilt->trx);
|
||||
|
||||
if (!str) {
|
||||
return((char*)comment);
|
||||
@ -3673,6 +3739,17 @@ ha_innobase::get_foreign_key_create_info(void)
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
|
||||
char* str;
|
||||
|
||||
/* We do not know if MySQL can call this function before calling
|
||||
external_lock(). To be safe, update the thd of the current table
|
||||
handle. */
|
||||
|
||||
update_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_search_latch_release_if_reserved(prebuilt->trx);
|
||||
|
||||
if (prebuilt == NULL) {
|
||||
fprintf(stderr,
|
||||
@ -3752,9 +3829,10 @@ ha_innobase::reset(void)
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
When we create a temporary table inside MySQL LOCK TABLES, MySQL will
|
||||
not call external_lock for the temporary table when it uses it. Instead,
|
||||
it will call this function. */
|
||||
Inside LOCK TABLES MySQL will not call external_lock() between SQL
|
||||
statements. It will call this function at the start of each SQL statement.
|
||||
Note also a spacial case: if a temporary table is created inside LOCK
|
||||
TABLES, MySQL has not called external_lock() at all on that table. */
|
||||
|
||||
int
|
||||
ha_innobase::start_stmt(
|
||||
@ -3892,8 +3970,8 @@ ha_innobase::external_lock(
|
||||
|
||||
trx->mysql_n_tables_locked = 0;
|
||||
|
||||
/* Here we release the search latch, auto_inc_lock,
|
||||
and InnoDB thread FIFO ticket if they were reserved. */
|
||||
/* Here we release the search latch and InnoDB
|
||||
thread FIFO ticket if they were reserved. */
|
||||
|
||||
innobase_release_stat_resources(trx);
|
||||
|
||||
@ -4209,4 +4287,4 @@ ha_innobase::get_auto_increment()
|
||||
}
|
||||
|
||||
#endif /* HAVE_INNOBASE_DB */
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user