2016-09-06 08:43:16 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
Copyright (c) 2016, MariaDB Corporation. All Rights Reserved.
|
2016-09-06 08:43:16 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
Foundation; version 2 of the License.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
|
|
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/**************************************************//**
|
|
|
|
@file dict/dict0defrag_bg.cc
|
|
|
|
Defragmentation routines.
|
|
|
|
|
|
|
|
Created 25/08/2016 Jan Lindström
|
|
|
|
*******************************************************/
|
|
|
|
|
|
|
|
#include "dict0dict.h"
|
|
|
|
#include "dict0stats.h"
|
|
|
|
#include "dict0stats_bg.h"
|
|
|
|
#include "dict0defrag_bg.h"
|
|
|
|
#include "row0mysql.h"
|
|
|
|
#include "srv0start.h"
|
|
|
|
#include "ut0new.h"
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
static ib_mutex_t defrag_pool_mutex;
|
|
|
|
|
|
|
|
#ifdef MYSQL_PFS
|
|
|
|
static mysql_pfs_key_t defrag_pool_mutex_key;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/** Indices whose defrag stats need to be saved to persistent storage.*/
|
|
|
|
struct defrag_pool_item_t {
|
|
|
|
table_id_t table_id;
|
|
|
|
index_id_t index_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Allocator type, used by std::vector */
|
|
|
|
typedef ut_allocator<defrag_pool_item_t>
|
|
|
|
defrag_pool_allocator_t;
|
|
|
|
|
|
|
|
/** The multitude of tables to be defragmented- an STL vector */
|
|
|
|
typedef std::vector<defrag_pool_item_t, defrag_pool_allocator_t>
|
|
|
|
defrag_pool_t;
|
|
|
|
|
|
|
|
/** Iterator type for iterating over the elements of objects of type
|
|
|
|
defrag_pool_t. */
|
|
|
|
typedef defrag_pool_t::iterator defrag_pool_iterator_t;
|
|
|
|
|
|
|
|
/** Pool where we store information on which tables are to be processed
|
|
|
|
by background defragmentation. */
|
|
|
|
static defrag_pool_t* defrag_pool;
|
|
|
|
|
|
|
|
extern bool dict_stats_start_shutdown;
|
|
|
|
|
|
|
|
/*****************************************************************//**
|
|
|
|
Initialize the defrag pool, called once during thread initialization. */
|
|
|
|
void
|
|
|
|
dict_defrag_pool_init(void)
|
|
|
|
/*=======================*/
|
|
|
|
{
|
|
|
|
ut_ad(!srv_read_only_mode);
|
|
|
|
/* JAN: TODO: MySQL 5.7 PSI
|
|
|
|
const PSI_memory_key key2 = mem_key_dict_defrag_pool_t;
|
|
|
|
|
|
|
|
defrag_pool = UT_NEW(defrag_pool_t(defrag_pool_allocator_t(key2)), key2);
|
|
|
|
|
|
|
|
recalc_pool->reserve(RECALC_POOL_INITIAL_SLOTS);
|
|
|
|
*/
|
|
|
|
defrag_pool = new std::vector<defrag_pool_item_t, defrag_pool_allocator_t>();
|
|
|
|
|
|
|
|
/* We choose SYNC_STATS_DEFRAG to be below SYNC_FSP_PAGE. */
|
|
|
|
mutex_create(LATCH_ID_DEFRAGMENT_MUTEX, &defrag_pool_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************//**
|
|
|
|
Free the resources occupied by the defrag pool, called once during
|
|
|
|
thread de-initialization. */
|
|
|
|
void
|
|
|
|
dict_defrag_pool_deinit(void)
|
|
|
|
/*=========================*/
|
|
|
|
{
|
|
|
|
ut_ad(!srv_read_only_mode);
|
|
|
|
|
|
|
|
defrag_pool->clear();
|
|
|
|
mutex_free(&defrag_pool_mutex);
|
|
|
|
|
|
|
|
UT_DELETE(defrag_pool);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************//**
|
|
|
|
Get an index from the auto defrag pool. The returned index id is removed
|
|
|
|
from the pool.
|
|
|
|
@return true if the pool was non-empty and "id" was set, false otherwise */
|
|
|
|
static
|
|
|
|
bool
|
|
|
|
dict_stats_defrag_pool_get(
|
|
|
|
/*=======================*/
|
|
|
|
table_id_t* table_id, /*!< out: table id, or unmodified if
|
|
|
|
list is empty */
|
|
|
|
index_id_t* index_id) /*!< out: index id, or unmodified if
|
|
|
|
list is empty */
|
|
|
|
{
|
|
|
|
ut_ad(!srv_read_only_mode);
|
|
|
|
|
|
|
|
mutex_enter(&defrag_pool_mutex);
|
|
|
|
|
|
|
|
if (defrag_pool->empty()) {
|
|
|
|
mutex_exit(&defrag_pool_mutex);
|
|
|
|
return(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
defrag_pool_item_t& item = defrag_pool->back();
|
|
|
|
*table_id = item.table_id;
|
|
|
|
*index_id = item.index_id;
|
|
|
|
|
|
|
|
defrag_pool->pop_back();
|
|
|
|
|
|
|
|
mutex_exit(&defrag_pool_mutex);
|
|
|
|
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************//**
|
|
|
|
Add an index in a table to the defrag pool, which is processed by the
|
|
|
|
background stats gathering thread. Only the table id and index id are
|
|
|
|
added to the list, so the table can be closed after being enqueued and
|
|
|
|
it will be opened when needed. If the table or index does not exist later
|
|
|
|
(has been DROPped), then it will be removed from the pool and skipped. */
|
|
|
|
void
|
|
|
|
dict_stats_defrag_pool_add(
|
|
|
|
/*=======================*/
|
|
|
|
const dict_index_t* index) /*!< in: table to add */
|
|
|
|
{
|
|
|
|
defrag_pool_item_t item;
|
|
|
|
|
|
|
|
ut_ad(!srv_read_only_mode);
|
|
|
|
|
|
|
|
mutex_enter(&defrag_pool_mutex);
|
|
|
|
|
|
|
|
/* quit if already in the list */
|
|
|
|
for (defrag_pool_iterator_t iter = defrag_pool->begin();
|
|
|
|
iter != defrag_pool->end();
|
|
|
|
++iter) {
|
|
|
|
if ((*iter).table_id == index->table->id
|
|
|
|
&& (*iter).index_id == index->id) {
|
|
|
|
mutex_exit(&defrag_pool_mutex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
item.table_id = index->table->id;
|
|
|
|
item.index_id = index->id;
|
|
|
|
defrag_pool->push_back(item);
|
|
|
|
|
|
|
|
mutex_exit(&defrag_pool_mutex);
|
|
|
|
|
|
|
|
os_event_set(dict_stats_event);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************//**
|
|
|
|
Delete a given index from the auto defrag pool. */
|
|
|
|
void
|
|
|
|
dict_stats_defrag_pool_del(
|
|
|
|
/*=======================*/
|
|
|
|
const dict_table_t* table, /*!<in: if given, remove
|
|
|
|
all entries for the table */
|
|
|
|
const dict_index_t* index) /*!< in: if given, remove this index */
|
|
|
|
{
|
|
|
|
ut_a((table && !index) || (!table && index));
|
|
|
|
ut_ad(!srv_read_only_mode);
|
|
|
|
ut_ad(mutex_own(&dict_sys->mutex));
|
|
|
|
|
|
|
|
mutex_enter(&defrag_pool_mutex);
|
|
|
|
|
|
|
|
defrag_pool_iterator_t iter = defrag_pool->begin();
|
|
|
|
while (iter != defrag_pool->end()) {
|
|
|
|
if ((table && (*iter).table_id == table->id)
|
|
|
|
|| (index
|
|
|
|
&& (*iter).table_id == index->table->id
|
|
|
|
&& (*iter).index_id == index->id)) {
|
|
|
|
/* erase() invalidates the iterator */
|
|
|
|
iter = defrag_pool->erase(iter);
|
|
|
|
if (index)
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
iter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_exit(&defrag_pool_mutex);
|
|
|
|
}
|
|
|
|
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
/*****************************************************************//**
|
|
|
|
Get the first index that has been added for updating persistent defrag
|
|
|
|
stats and eventually save its stats. */
|
2016-09-06 08:43:16 +02:00
|
|
|
static
|
|
|
|
void
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
dict_stats_process_entry_from_defrag_pool()
|
2016-09-06 08:43:16 +02:00
|
|
|
{
|
|
|
|
table_id_t table_id;
|
|
|
|
index_id_t index_id;
|
|
|
|
|
|
|
|
ut_ad(!srv_read_only_mode);
|
|
|
|
|
|
|
|
/* pop the first index from the auto defrag pool */
|
|
|
|
if (!dict_stats_defrag_pool_get(&table_id, &index_id)) {
|
|
|
|
/* no index in defrag pool */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dict_table_t* table;
|
|
|
|
|
|
|
|
mutex_enter(&dict_sys->mutex);
|
|
|
|
|
|
|
|
/* If the table is no longer cached, we've already lost the in
|
|
|
|
memory stats so there's nothing really to write to disk. */
|
|
|
|
table = dict_table_open_on_id(table_id, TRUE,
|
|
|
|
DICT_TABLE_OP_OPEN_ONLY_IF_CACHED);
|
|
|
|
|
2017-12-05 13:23:57 +01:00
|
|
|
dict_index_t* index = table && !table->corrupted
|
|
|
|
? dict_table_find_index_on_id(table, index_id)
|
|
|
|
: NULL;
|
2016-09-06 08:43:16 +02:00
|
|
|
|
2017-12-05 13:23:57 +01:00
|
|
|
if (!index || dict_index_is_corrupted(index)) {
|
|
|
|
if (table) {
|
|
|
|
dict_table_close(table, TRUE, FALSE);
|
|
|
|
}
|
2016-09-06 08:43:16 +02:00
|
|
|
mutex_exit(&dict_sys->mutex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-25 10:28:38 +01:00
|
|
|
mutex_exit(&dict_sys->mutex);
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
dict_stats_save_defrag_stats(index);
|
2016-09-06 08:43:16 +02:00
|
|
|
dict_table_close(table, FALSE, FALSE);
|
|
|
|
}
|
|
|
|
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
/*****************************************************************//**
|
|
|
|
Get the first index that has been added for updating persistent defrag
|
|
|
|
stats and eventually save its stats. */
|
2016-09-06 08:43:16 +02:00
|
|
|
void
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
dict_defrag_process_entries_from_defrag_pool()
|
|
|
|
/*==========================================*/
|
2016-09-06 08:43:16 +02:00
|
|
|
{
|
|
|
|
while (defrag_pool->size() && !dict_stats_start_shutdown) {
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
dict_stats_process_entry_from_defrag_pool();
|
2016-09-06 08:43:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
/*********************************************************************//**
|
|
|
|
Save defragmentation result.
|
2016-09-06 08:43:16 +02:00
|
|
|
@return DB_SUCCESS or error code */
|
|
|
|
dberr_t
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
dict_stats_save_defrag_summary(
|
|
|
|
/*============================*/
|
|
|
|
dict_index_t* index) /*!< in: index */
|
2016-09-06 08:43:16 +02:00
|
|
|
{
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
dberr_t ret=DB_SUCCESS;
|
|
|
|
lint now = (lint) ut_time();
|
2017-12-11 09:06:32 +01:00
|
|
|
|
2017-09-19 20:53:08 +02:00
|
|
|
if (dict_index_is_ibuf(index)) {
|
2016-09-06 08:43:16 +02:00
|
|
|
return DB_SUCCESS;
|
|
|
|
}
|
|
|
|
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
rw_lock_x_lock(dict_operation_lock);
|
|
|
|
mutex_enter(&dict_sys->mutex);
|
|
|
|
|
|
|
|
ret = dict_stats_save_index_stat(index, now, "n_pages_freed",
|
|
|
|
index->stat_defrag_n_pages_freed,
|
|
|
|
NULL,
|
|
|
|
"Number of pages freed during"
|
|
|
|
" last defragmentation run.",
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
mutex_exit(&dict_sys->mutex);
|
|
|
|
rw_lock_x_unlock(dict_operation_lock);
|
|
|
|
|
|
|
|
return (ret);
|
2016-09-06 08:43:16 +02:00
|
|
|
}
|
|
|
|
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
/*********************************************************************//**
|
|
|
|
Save defragmentation stats for a given index.
|
2016-09-06 08:43:16 +02:00
|
|
|
@return DB_SUCCESS or error code */
|
|
|
|
dberr_t
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
dict_stats_save_defrag_stats(
|
|
|
|
/*============================*/
|
|
|
|
dict_index_t* index) /*!< in: index */
|
2016-09-06 08:43:16 +02:00
|
|
|
{
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
dberr_t ret;
|
2017-12-11 09:06:32 +01:00
|
|
|
|
2017-09-19 20:53:08 +02:00
|
|
|
if (dict_index_is_ibuf(index)) {
|
2016-09-06 08:43:16 +02:00
|
|
|
return DB_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-05-05 09:25:29 +02:00
|
|
|
if (!index->is_readable()) {
|
|
|
|
return dict_stats_report_error(index->table, true);
|
|
|
|
}
|
|
|
|
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
lint now = (lint) ut_time();
|
2016-09-06 08:43:16 +02:00
|
|
|
mtr_t mtr;
|
|
|
|
ulint n_leaf_pages;
|
|
|
|
ulint n_leaf_reserved;
|
|
|
|
mtr_start(&mtr);
|
|
|
|
mtr_s_lock(dict_index_get_lock(index), &mtr);
|
|
|
|
n_leaf_reserved = btr_get_size_and_reserved(index, BTR_N_LEAF_PAGES,
|
|
|
|
&n_leaf_pages, &mtr);
|
|
|
|
mtr_commit(&mtr);
|
|
|
|
|
|
|
|
if (n_leaf_reserved == ULINT_UNDEFINED) {
|
|
|
|
// The index name is different during fast index creation,
|
|
|
|
// so the stats won't be associated with the right index
|
|
|
|
// for later use. We just return without saving.
|
|
|
|
return DB_SUCCESS;
|
|
|
|
}
|
|
|
|
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
rw_lock_x_lock(dict_operation_lock);
|
|
|
|
|
|
|
|
mutex_enter(&dict_sys->mutex);
|
|
|
|
ret = dict_stats_save_index_stat(index, now, "n_page_split",
|
|
|
|
index->stat_defrag_n_page_split,
|
|
|
|
NULL,
|
|
|
|
"Number of new page splits on leaves"
|
|
|
|
" since last defragmentation.",
|
|
|
|
NULL);
|
|
|
|
if (ret != DB_SUCCESS) {
|
|
|
|
goto end;
|
2016-09-06 08:43:16 +02:00
|
|
|
}
|
|
|
|
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
ret = dict_stats_save_index_stat(
|
|
|
|
index, now, "n_leaf_pages_defrag",
|
|
|
|
n_leaf_pages,
|
|
|
|
NULL,
|
|
|
|
"Number of leaf pages when this stat is saved to disk",
|
|
|
|
NULL);
|
|
|
|
if (ret != DB_SUCCESS) {
|
|
|
|
goto end;
|
MDEV-14511 Use fewer transactions for updating InnoDB persistent statistics
dict_stats_exec_sql(): Expect the caller to always provide a transaction.
Remove some redundant assertions. The caller must hold dict_sys->mutex,
but holding dict_operation_lock is only necessary for accessing
data dictionary tables, which we are not accessing.
dict_stats_save_index_stat(): Acquire dict_sys->mutex
for invoking dict_stats_exec_sql().
dict_stats_save(), dict_stats_update_for_index(), dict_stats_update(),
dict_stats_drop_index(), dict_stats_delete_from_table_stats(),
dict_stats_delete_from_index_stats(), dict_stats_drop_table(),
dict_stats_rename_in_table_stats(), dict_stats_rename_in_index_stats(),
dict_stats_rename_table(): Use a single caller-provided
transaction that is started and committed or rolled back by the caller.
dict_stats_process_entry_from_recalc_pool(): Let the caller provide
a transaction object.
ha_innobase::open(): Pass a transaction to dict_stats_init().
ha_innobase::create(), ha_innobase::discard_or_import_tablespace():
Pass a transaction to dict_stats_update().
ha_innobase::rename_table(): Pass a transaction to
dict_stats_rename_table(). We do not use the same transaction
as the one that updated the data dictionary tables, because
we already released the dict_operation_lock. (FIXME: there is
a race condition; a lock wait on SYS_* tables could occur
in another DDL transaction until the data dictionary transaction
is committed.)
ha_innobase::info_low(): Pass a transaction to dict_stats_update()
when calculating persistent statistics.
alter_stats_norebuild(), alter_stats_rebuild(): Update the
persistent statistics as well. In this way, a single transaction
will be used for updating the statistics of a whole table, even
for partitioned tables.
ha_innobase::commit_inplace_alter_table(): Drop statistics for
all partitions when adding or dropping virtual columns, so that
the statistics will be recalculated on the next handler::open().
This is a refactored version of Oracle Bug#22469660 fix.
RecLock::add_to_waitq(), lock_table_enqueue_waiting():
Do not allow a lock wait to occur for updating statistics
in a data dictionary transaction, such as DROP TABLE. Instead,
return the previously unused error code DB_QUE_THR_SUSPENDED.
row_merge_lock_table(), row_mysql_lock_table(): Remove dead code
for handling DB_QUE_THR_SUSPENDED.
row_drop_table_for_mysql(), row_truncate_table_for_mysql():
Drop the statistics as part of the data dictionary transaction.
After TRUNCATE TABLE, the statistics will be recalculated on
subsequent ha_innobase::open(), similar to how the logic after
the above-mentioned Oracle Bug#22469660 fix in
ha_innobase::commit_inplace_alter_table() works.
btr_defragment_thread(): Use a single transaction object for
updating defragmentation statistics.
dict_stats_save_defrag_stats(), dict_stats_save_defrag_stats(),
dict_stats_process_entry_from_defrag_pool(),
dict_defrag_process_entries_from_defrag_pool(),
dict_stats_save_defrag_summary(), dict_stats_save_defrag_stats():
Add a parameter for the transaction.
dict_stats_empty_table(): Make public. This will be called by
row_truncate_table_for_mysql() after dropping persistent statistics,
to clear the memory-based statistics as well.
2017-12-01 15:51:24 +01:00
|
|
|
}
|
2016-09-06 08:43:16 +02:00
|
|
|
|
MDEV-14941 Timeouts on persistent statistics tables caused by MDEV-14511
MDEV-14511 tried to avoid some consistency problems related to InnoDB
persistent statistics. The persistent statistics are being written by
an InnoDB internal SQL interpreter that requires the InnoDB data dictionary
cache to be locked.
Before MDEV-14511, the statistics were written during DDL in separate
transactions, which could unnecessarily reduce performance (each commit
would require a redo log flush) and break atomicity, because the statistics
would be updated separately from the dictionary transaction.
However, because it is unacceptable to hold the InnoDB data dictionary
cache locked while suspending the execution for waiting for a
transactional lock (in the mysql.innodb_index_stats or
mysql.innodb_table_stats tables) to be released, any lock conflict
was immediately be reported as "lock wait timeout".
To fix MDEV-14941, an attempt to reduce these lock conflicts by acquiring
transactional locks on the user tables in both the statistics and DDL
operations was made, but it would still not entirely prevent lock conflicts
on the mysql.innodb_index_stats and mysql.innodb_table_stats tables.
Fixing the remaining problems would require a change that is too intrusive
for a GA release series, such as MariaDB 10.2.
Thefefore, we revert the change MDEV-14511. To silence the
MDEV-13201 assertion, we use the pre-existing flag trx_t::internal.
2018-01-21 17:23:28 +01:00
|
|
|
ret = dict_stats_save_index_stat(
|
|
|
|
index, now, "n_leaf_pages_reserved",
|
|
|
|
n_leaf_reserved,
|
|
|
|
NULL,
|
|
|
|
"Number of pages reserved for this index leaves when this stat "
|
|
|
|
"is saved to disk",
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
end:
|
|
|
|
mutex_exit(&dict_sys->mutex);
|
|
|
|
rw_lock_x_unlock(dict_operation_lock);
|
|
|
|
|
|
|
|
return (ret);
|
2016-09-06 08:43:16 +02:00
|
|
|
}
|