summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-08-03 15:57:23 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-08-03 15:57:23 +0300
commit05459706f22b1d9d22abd24e6de3b505d787beb3 (patch)
tree3e850e0cbf5489fbf36f5c1579248e344bfe2395 /storage/innobase
parent8ae2a2dbe6fc52d40ec88c325b9a44de52f83f2f (diff)
parente6a808bec790fdbbf1dc0a6b03fb6c8b6e41dc01 (diff)
downloadmariadb-git-05459706f22b1d9d22abd24e6de3b505d787beb3.tar.gz
Merge 10.2 into 10.3
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/btr/btr0cur.cc179
-rw-r--r--storage/innobase/buf/buf0buddy.cc2
-rw-r--r--storage/innobase/buf/buf0buf.cc4
-rw-r--r--storage/innobase/buf/buf0dump.cc2
-rw-r--r--storage/innobase/buf/buf0lru.cc2
-rw-r--r--storage/innobase/dict/dict0defrag_bg.cc47
-rw-r--r--storage/innobase/dict/dict0dict.cc100
-rw-r--r--storage/innobase/dict/dict0stats.cc8
-rw-r--r--storage/innobase/dict/dict0stats_bg.cc100
-rw-r--r--storage/innobase/fts/fts0ast.cc9
-rw-r--r--storage/innobase/fts/fts0fts.cc76
-rw-r--r--storage/innobase/fts/fts0opt.cc169
-rw-r--r--storage/innobase/fts/fts0pars.cc16
-rw-r--r--storage/innobase/fts/fts0pars.y16
-rw-r--r--storage/innobase/fts/fts0que.cc21
-rw-r--r--storage/innobase/gis/gis0rtree.cc4
-rw-r--r--storage/innobase/gis/gis0sea.cc2
-rw-r--r--storage/innobase/handler/ha_innodb.cc48
-rw-r--r--storage/innobase/handler/handler0alter.cc65
-rw-r--r--storage/innobase/handler/i_s.cc8
-rw-r--r--storage/innobase/include/btr0cur.h20
-rw-r--r--storage/innobase/include/btr0pcur.h12
-rw-r--r--storage/innobase/include/dict0defrag_bg.h19
-rw-r--r--storage/innobase/include/dict0dict.h8
-rw-r--r--storage/innobase/include/dict0mem.h3
-rw-r--r--storage/innobase/include/dict0stats.h18
-rw-r--r--storage/innobase/include/fts0ast.h5
-rw-r--r--storage/innobase/include/fts0fts.h10
-rw-r--r--storage/innobase/include/fts0priv.h11
-rw-r--r--storage/innobase/include/row0ftsort.h10
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/lock/lock0lock.cc5
-rw-r--r--storage/innobase/os/os0file.cc27
-rw-r--r--storage/innobase/row/row0ftsort.cc1
-rw-r--r--storage/innobase/row/row0import.cc89
-rw-r--r--storage/innobase/row/row0ins.cc3
-rw-r--r--storage/innobase/row/row0mysql.cc16
-rw-r--r--storage/innobase/row/row0purge.cc14
-rw-r--r--storage/innobase/row/row0trunc.cc14
-rw-r--r--storage/innobase/row/row0uins.cc5
-rw-r--r--storage/innobase/row/row0umod.cc3
-rw-r--r--storage/innobase/sync/sync0rw.cc99
-rw-r--r--storage/innobase/trx/trx0rseg.cc4
-rw-r--r--storage/innobase/trx/trx0trx.cc3
44 files changed, 656 insertions, 623 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 11dc5b43059..3d8d08573f7 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2015, 2018, MariaDB Corporation.
@@ -65,6 +65,8 @@ Created 10/16/1994 Heikki Tuuri
#include "lock0lock.h"
#include "zlib.h"
#include "srv0start.h"
+#include "mysql_com.h"
+#include "dict0stats.h"
/** Buffered B-tree operation types, introduced as part of delete buffering. */
enum btr_op_t {
@@ -781,13 +783,15 @@ btr_cur_will_modify_tree(
first record and following compress might delete the record and causes
the uppper level node_ptr modification. */
+ const ulint n_recs = page_get_n_recs(page);
+
if (lock_intention <= BTR_INTENTION_BOTH) {
ulint margin;
/* check delete will cause. (BTR_INTENTION_BOTH
or BTR_INTENTION_DELETE) */
/* first, 2nd, 2nd-last and last records are 4 records */
- if (page_get_n_recs(page) < 5) {
+ if (n_recs < 5) {
return(true);
}
@@ -833,8 +837,7 @@ btr_cur_will_modify_tree(
/* Once we invoke the btr_cur_limit_optimistic_insert_debug,
we should check it here in advance, since the max allowable
records in a page is limited. */
- LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page),
- return(true));
+ LIMIT_OPTIMISTIC_INSERT_DEBUG(n_recs, return true);
/* needs 2 records' space for the case the single split and
insert cannot fit.
@@ -847,18 +850,16 @@ btr_cur_will_modify_tree(
|| max_size < rec_size * 2) {
return(true);
}
- /* TODO: optimize this condition for compressed page.
- this is based on the worst compress rate.
- currently looking only uncompressed page, but we can look
- also compressed page page_zip_available() if already in the
- buffer pool */
+
+ /* TODO: optimize this condition for ROW_FORMAT=COMPRESSED.
+ This is based on the worst case, and we could invoke
+ page_zip_available() on the block->page.zip. */
/* needs 2 records' space also for worst compress rate. */
if (page_size.is_compressed()
&& page_zip_empty_size(index->n_fields,
page_size.physical())
- < rec_size * 2 + page_get_data_size(page)
- + page_dir_calc_reserved_space(
- ulint(page_get_n_recs(page)) + 2) + 1) {
+ <= rec_size * 2 + page_get_data_size(page)
+ + page_dir_calc_reserved_space(n_recs + 2)) {
return(true);
}
}
@@ -893,6 +894,114 @@ btr_cur_need_opposite_intention(
return(false);
}
+/**
+@param[in] index b-tree
+@return maximum size of a node pointer record in bytes */
+static ulint btr_node_ptr_max_size(const dict_index_t* index)
+{
+ if (dict_index_is_ibuf(index)) {
+ /* cannot estimate accurately */
+ /* This is universal index for change buffer.
+ The max size of the entry is about max key length * 2.
+ (index key + primary key to be inserted to the index)
+ (The max key length is UNIV_PAGE_SIZE / 16 * 3 at
+ ha_innobase::max_supported_key_length(),
+ considering MAX_KEY_LENGTH = 3072 at MySQL imposes
+ the 3500 historical InnoDB value for 16K page size case.)
+ For the universal index, node_ptr contains most of the entry.
+ And 512 is enough to contain ibuf columns and meta-data */
+ return srv_page_size / 8 * 3 + 512;
+ }
+
+ /* Each record has page_no, length of page_no and header. */
+ ulint comp = dict_table_is_comp(index->table);
+ ulint rec_max_size = comp
+ ? REC_NODE_PTR_SIZE + 1 + REC_N_NEW_EXTRA_BYTES
+ + UT_BITS_IN_BYTES(index->n_nullable)
+ : REC_NODE_PTR_SIZE + 2 + REC_N_OLD_EXTRA_BYTES
+ + 2 * index->n_fields;
+
+ /* Compute the maximum possible record size. */
+ for (ulint i = 0; i < dict_index_get_n_unique_in_tree(index); i++) {
+ const dict_field_t* field
+ = dict_index_get_nth_field(index, i);
+ const dict_col_t* col
+ = dict_field_get_col(field);
+ ulint field_max_size;
+ ulint field_ext_max_size;
+
+ /* Determine the maximum length of the index field. */
+
+ field_max_size = dict_col_get_fixed_size(col, comp);
+ if (field_max_size) {
+ /* dict_index_add_col() should guarantee this */
+ ut_ad(!field->prefix_len
+ || field->fixed_len == field->prefix_len);
+ /* Fixed lengths are not encoded
+ in ROW_FORMAT=COMPACT. */
+ rec_max_size += field_max_size;
+ continue;
+ }
+
+ field_max_size = dict_col_get_max_size(col);
+ if (UNIV_UNLIKELY(!field_max_size)) {
+ /* SYS_FOREIGN.ID is defined as CHAR in the
+ InnoDB internal SQL parser, which translates
+ into the incorrect VARCHAR(0). InnoDB does
+ not enforce maximum lengths of columns, so
+ that is why any data can be inserted in the
+ first place.
+
+ Likewise, SYS_FOREIGN.FOR_NAME,
+ SYS_FOREIGN.REF_NAME, SYS_FOREIGN_COLS.ID, are
+ defined as CHAR, and also they are part of a key. */
+
+ ut_ad(!strcmp(index->table->name.m_name,
+ "SYS_FOREIGN")
+ || !strcmp(index->table->name.m_name,
+ "SYS_FOREIGN_COLS"));
+ ut_ad(!comp);
+
+ rec_max_size += (srv_page_size == UNIV_PAGE_SIZE_MAX)
+ ? REDUNDANT_REC_MAX_DATA_SIZE
+ : page_get_free_space_of_empty(FALSE) / 2;
+ } else if (field_max_size == NAME_LEN && i == 1
+ && (!strcmp(index->table->name.m_name,
+ TABLE_STATS_NAME)
+ || !strcmp(index->table->name.m_name,
+ INDEX_STATS_NAME))) {
+ ut_ad(!strcmp(field->name, "table_name"));
+ /* Interpret "table_name" as VARCHAR(199) even
+ if it was incorrectly defined as VARCHAR(64).
+ While the caller of ha_innobase enforces the
+ maximum length on any data written, the InnoDB
+ internal SQL parser will happily write as much
+ data as is provided. The purpose of this hack
+ is to avoid InnoDB hangs after persistent
+ statistics on partitioned tables are
+ deleted. */
+ field_max_size = 199 * SYSTEM_CHARSET_MBMAXLEN;
+ }
+ field_ext_max_size = field_max_size < 256 ? 1 : 2;
+
+ if (field->prefix_len
+ && field->prefix_len < field_max_size) {
+ field_max_size = field->prefix_len;
+ }
+
+ if (comp) {
+ /* Add the extra size for ROW_FORMAT=COMPACT.
+ For ROW_FORMAT=REDUNDANT, these bytes were
+ added to rec_max_size before this loop. */
+ rec_max_size += field_ext_max_size;
+ }
+
+ rec_max_size += field_max_size;
+ }
+
+ return rec_max_size;
+}
+
/********************************************************************//**
Searches an index tree and positions a tree cursor on a given level.
NOTE: n_fields_cmp in tuple must be set so that it cannot be compared
@@ -1218,7 +1327,7 @@ btr_cur_search_to_nth_level_func(
page_id_t page_id(index->table->space->id, index->page);
if (root_leaf_rw_latch == RW_X_LATCH) {
- node_ptr_max_size = dict_index_node_ptr_max_size(index);
+ node_ptr_max_size = btr_node_ptr_max_size(index);
}
up_match = 0;
@@ -2327,7 +2436,7 @@ btr_cur_open_at_index_side_func(
const page_size_t page_size(index->table->space->flags);
if (root_leaf_rw_latch == RW_X_LATCH) {
- node_ptr_max_size = dict_index_node_ptr_max_size(index);
+ node_ptr_max_size = btr_node_ptr_max_size(index);
}
height = ULINT_UNDEFINED;
@@ -2685,7 +2794,7 @@ btr_cur_open_at_rnd_pos_func(
dberr_t err = DB_SUCCESS;
if (root_leaf_rw_latch == RW_X_LATCH) {
- node_ptr_max_size = dict_index_node_ptr_max_size(index);
+ node_ptr_max_size = btr_node_ptr_max_size(index);
}
height = ULINT_UNDEFINED;
@@ -5657,23 +5766,45 @@ discard_page:
}
}
- page_cur_delete_rec(btr_cur_get_page_cur(cursor), index, offsets, mtr);
+ /* SPATIAL INDEX never use SX locks; we can allow page merges
+ while holding X lock on the spatial index tree.
+ Do not allow merges of non-leaf B-tree pages unless it is
+ safe to do so. */
+ {
+ const bool allow_merge = page_is_leaf(page)
+ || dict_index_is_spatial(index)
+ || btr_cur_will_modify_tree(
+ index, page, BTR_INTENTION_DELETE, rec,
+ btr_node_ptr_max_size(index),
+ block->page.size, mtr);
+ page_cur_delete_rec(btr_cur_get_page_cur(cursor), index,
+ offsets, mtr);
#ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(page_zip, page, index));
+ ut_a(!page_zip || page_zip_validate(page_zip, page, index));
#endif /* UNIV_ZIP_DEBUG */
-return_after_reservations:
- /* btr_check_node_ptr() needs parent block latched */
- ut_ad(!parent_latched || btr_check_node_ptr(index, block, mtr));
+ ut_ad(!parent_latched
+ || btr_check_node_ptr(index, block, mtr));
+
+ if (!ret && btr_cur_compress_recommendation(cursor, mtr)) {
+ if (UNIV_LIKELY(allow_merge)) {
+ ret = btr_cur_compress_if_useful(
+ cursor, FALSE, mtr);
+ } else {
+ ib::warn() << "Not merging page "
+ << block->page.id
+ << " in index " << index->name
+ << " of " << index->table->name;
+ ut_ad(!"MDEV-14637");
+ }
+ }
+ }
+return_after_reservations:
*err = DB_SUCCESS;
mem_heap_free(heap);
- if (ret == FALSE) {
- ret = btr_cur_compress_if_useful(cursor, FALSE, mtr);
- }
-
if (!srv_read_only_mode
&& page_is_leaf(page)
&& !dict_index_is_online_ddl(index)) {
diff --git a/storage/innobase/buf/buf0buddy.cc b/storage/innobase/buf/buf0buddy.cc
index 27a45654966..f932195897c 100644
--- a/storage/innobase/buf/buf0buddy.cc
+++ b/storage/innobase/buf/buf0buddy.cc
@@ -124,7 +124,7 @@ buf_buddy_stamp_free(
buf_buddy_free_t* buf, /*!< in/out: block to stamp */
ulint i) /*!< in: block size */
{
- ut_d(memset(buf, static_cast<int>(i), BUF_BUDDY_LOW << i));
+ ut_d(memset(&buf->stamp.bytes, int(i), BUF_BUDDY_LOW << i));
buf_buddy_mem_invalid(buf, i);
mach_write_to_4(buf->stamp.bytes + BUF_BUDDY_STAMP_OFFSET,
BUF_BUDDY_STAMP_FREE);
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index f053c170c0e..bd64334c3ba 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -2258,7 +2258,7 @@ buf_page_realloc(
mutex_enter(&new_block->mutex);
memcpy(new_block->frame, block->frame, srv_page_size);
- memcpy(&new_block->page, &block->page, sizeof block->page);
+ new (&new_block->page) buf_page_t(block->page);
/* relocate LRU list */
ut_ad(block->page.in_LRU_list);
@@ -3389,7 +3389,7 @@ buf_relocate(
}
#endif /* UNIV_DEBUG */
- memcpy(dpage, bpage, sizeof *dpage);
+ new (dpage) buf_page_t(*bpage);
/* Important that we adjust the hazard pointer before
removing bpage from LRU list. */
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc
index a0c4baad64d..7ede67fd0e4 100644
--- a/storage/innobase/buf/buf0dump.cc
+++ b/storage/innobase/buf/buf0dump.cc
@@ -262,7 +262,7 @@ buf_dump(
#define SHOULD_QUIT() (SHUTTING_DOWN() && obey_shutdown)
char full_filename[OS_FILE_MAX_PATH];
- char tmp_filename[OS_FILE_MAX_PATH];
+ char tmp_filename[OS_FILE_MAX_PATH + sizeof "incomplete"];
char now[32];
FILE* f;
ulint i;
diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc
index ebd5c2a828b..125c5beb47c 100644
--- a/storage/innobase/buf/buf0lru.cc
+++ b/storage/innobase/buf/buf0lru.cc
@@ -1610,7 +1610,7 @@ func_exit:
} else if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) {
b = buf_page_alloc_descriptor();
ut_a(b);
- memcpy(b, bpage, sizeof *b);
+ new (b) buf_page_t(*bpage);
}
ut_ad(buf_pool_mutex_own(buf_pool));
diff --git a/storage/innobase/dict/dict0defrag_bg.cc b/storage/innobase/dict/dict0defrag_bg.cc
index 949bbbc0d74..69038d4cb77 100644
--- a/storage/innobase/dict/dict0defrag_bg.cc
+++ b/storage/innobase/dict/dict0defrag_bg.cc
@@ -39,27 +39,13 @@ static ib_mutex_t defrag_pool_mutex;
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;
+defrag_pool_t defrag_pool;
extern bool dict_stats_start_shutdown;
@@ -70,14 +56,6 @@ 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);
@@ -92,10 +70,7 @@ dict_defrag_pool_deinit(void)
{
ut_ad(!srv_read_only_mode);
- defrag_pool->clear();
mutex_free(&defrag_pool_mutex);
-
- UT_DELETE(defrag_pool);
}
/*****************************************************************//**
@@ -115,16 +90,16 @@ dict_stats_defrag_pool_get(
mutex_enter(&defrag_pool_mutex);
- if (defrag_pool->empty()) {
+ if (defrag_pool.empty()) {
mutex_exit(&defrag_pool_mutex);
return(false);
}
- defrag_pool_item_t& item = defrag_pool->back();
+ defrag_pool_item_t& item = defrag_pool.back();
*table_id = item.table_id;
*index_id = item.index_id;
- defrag_pool->pop_back();
+ defrag_pool.pop_back();
mutex_exit(&defrag_pool_mutex);
@@ -149,8 +124,8 @@ dict_stats_defrag_pool_add(
mutex_enter(&defrag_pool_mutex);
/* quit if already in the list */
- for (defrag_pool_iterator_t iter = defrag_pool->begin();
- iter != defrag_pool->end();
+ 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) {
@@ -161,7 +136,7 @@ dict_stats_defrag_pool_add(
item.table_id = index->table->id;
item.index_id = index->id;
- defrag_pool->push_back(item);
+ defrag_pool.push_back(item);
mutex_exit(&defrag_pool_mutex);
@@ -183,14 +158,14 @@ dict_stats_defrag_pool_del(
mutex_enter(&defrag_pool_mutex);
- defrag_pool_iterator_t iter = defrag_pool->begin();
- while (iter != defrag_pool->end()) {
+ 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);
+ iter = defrag_pool.erase(iter);
if (index)
break;
} else {
@@ -252,7 +227,7 @@ void
dict_defrag_process_entries_from_defrag_pool()
/*==========================================*/
{
- while (defrag_pool->size() && !dict_stats_start_shutdown) {
+ while (defrag_pool.size() && !dict_stats_start_shutdown) {
dict_stats_process_entry_from_defrag_pool();
}
}
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index f088e6d356c..51190ff2ef6 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -2089,93 +2089,6 @@ dict_col_name_is_reserved(
}
/****************************************************************//**
-Return maximum size of the node pointer record.
-@return maximum size of the record in bytes */
-ulint
-dict_index_node_ptr_max_size(
-/*=========================*/
- const dict_index_t* index) /*!< in: index */
-{
- ulint comp;
- ulint i;
- /* maximum possible storage size of a record */
- ulint rec_max_size;
-
- if (dict_index_is_ibuf(index)) {
- /* cannot estimate accurately */
- /* This is universal index for change buffer.
- The max size of the entry is about max key length * 2.
- (index key + primary key to be inserted to the index)
- (The max key length is srv_page_size / 16 * 3 at
- ha_innobase::max_supported_key_length(),
- considering MAX_KEY_LENGTH = 3072 at MySQL imposes
- the 3500 historical InnoDB value for 16K page size case.)
- For the universal index, node_ptr contains most of the entry.
- And 512 is enough to contain ibuf columns and meta-data */
- return(srv_page_size / 8 * 3 + 512);
- }
-
- comp = dict_table_is_comp(index->table);
-
- /* Each record has page_no, length of page_no and header. */
- rec_max_size = comp
- ? REC_NODE_PTR_SIZE + 1 + REC_N_NEW_EXTRA_BYTES
- : REC_NODE_PTR_SIZE + 2 + REC_N_OLD_EXTRA_BYTES;
-
- if (comp) {
- /* Include the "null" flags in the
- maximum possible record size. */
- rec_max_size += UT_BITS_IN_BYTES(unsigned(index->n_nullable));
- } else {
- /* For each column, include a 2-byte offset and a
- "null" flag. */
- rec_max_size += 2 * unsigned(index->n_fields);
- }
-
- /* Compute the maximum possible record size. */
- for (i = 0; i < dict_index_get_n_unique_in_tree(index); i++) {
- const dict_field_t* field
- = dict_index_get_nth_field(index, i);
- const dict_col_t* col
- = dict_field_get_col(field);
- ulint field_max_size;
- ulint field_ext_max_size;
-
- /* Determine the maximum length of the index field. */
-
- field_max_size = dict_col_get_fixed_size(col, comp);
- if (field_max_size) {
- /* dict_index_add_col() should guarantee this */
- ut_ad(!field->prefix_len
- || field->fixed_len == field->prefix_len);
- /* Fixed lengths are not encoded
- in ROW_FORMAT=COMPACT. */
- rec_max_size += field_max_size;
- continue;
- }
-
- field_max_size = dict_col_get_max_size(col);
- field_ext_max_size = field_max_size < 256 ? 1 : 2;
-
- if (field->prefix_len
- && field->prefix_len < field_max_size) {
- field_max_size = field->prefix_len;
- }
-
- if (comp) {
- /* Add the extra size for ROW_FORMAT=COMPACT.
- For ROW_FORMAT=REDUNDANT, these bytes were
- added to rec_max_size before this loop. */
- rec_max_size += field_ext_max_size;
- }
-
- rec_max_size += field_max_size;
- }
-
- return(rec_max_size);
-}
-
-/****************************************************************//**
If a record of this index might not fit on a single B-tree page,
return TRUE.
@return TRUE if the index record could become too big */
@@ -6460,8 +6373,17 @@ dict_table_schema_check(
compare column types and flags */
/* check length for exact match */
- if (req_schema->columns[i].len != table->cols[j].len) {
-
+ if (req_schema->columns[i].len == table->cols[j].len) {
+ } else if (!strcmp(req_schema->table_name, TABLE_STATS_NAME)
+ || !strcmp(req_schema->table_name,
+ INDEX_STATS_NAME)) {
+ ut_ad(table->cols[j].len < req_schema->columns[i].len);
+ ib::warn() << "Table " << req_schema->table_name
+ << " has length mismatch in the"
+ << " column name "
+ << req_schema->columns[i].name
+ << ". Please run mysql_upgrade";
+ } else {
CREATE_TYPES_NAMES();
snprintf(errstr, errstr_sz,
diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc
index 51dcdc9e140..69eebab8e17 100644
--- a/storage/innobase/dict/dict0stats.cc
+++ b/storage/innobase/dict/dict0stats.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2009, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2009, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -108,9 +108,7 @@ where n=1..n_uniq.
@} */
/* names of the tables from the persistent statistics storage */
-#define TABLE_STATS_NAME "mysql/innodb_table_stats"
#define TABLE_STATS_NAME_PRINT "mysql.innodb_table_stats"
-#define INDEX_STATS_NAME "mysql/innodb_index_stats"
#define INDEX_STATS_NAME_PRINT "mysql.innodb_index_stats"
#ifdef UNIV_STATS_DEBUG
@@ -181,7 +179,7 @@ dict_stats_persistent_storage_check(
DATA_NOT_NULL, 192},
{"table_name", DATA_VARMYSQL,
- DATA_NOT_NULL, 192},
+ DATA_NOT_NULL, 597},
{"last_update", DATA_FIXBINARY,
DATA_NOT_NULL, 4},
@@ -209,7 +207,7 @@ dict_stats_persistent_storage_check(
DATA_NOT_NULL, 192},
{"table_name", DATA_VARMYSQL,
- DATA_NOT_NULL, 192},
+ DATA_NOT_NULL, 597},
{"index_name", DATA_VARMYSQL,
DATA_NOT_NULL, 192},
diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc
index 6fde5654dd1..f15e98b8a4d 100644
--- a/storage/innobase/dict/dict0stats_bg.cc
+++ b/storage/innobase/dict/dict0stats_bg.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2018, 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
@@ -32,6 +32,12 @@ Created Apr 25, 2012 Vasil Dimov
#include "srv0start.h"
#include "ut0new.h"
#include "fil0fil.h"
+#ifdef WITH_WSREP
+# include "mysql/service_wsrep.h"
+# include "wsrep.h"
+# include "log.h"
+# include "wsrep_mysqld.h"
+#endif
#include <vector>
@@ -76,41 +82,31 @@ typedef recalc_pool_t::iterator
/** Pool where we store information on which tables are to be processed
by background statistics gathering. */
-static recalc_pool_t* recalc_pool;
-
-
-/*****************************************************************//**
-Initialize the recalc pool, called once during thread initialization. */
-static
-void
-dict_stats_recalc_pool_init()
-/*=========================*/
-{
- ut_ad(!srv_read_only_mode);
- /* JAN: TODO: MySQL 5.7 PSI
- const PSI_memory_key key = mem_key_dict_stats_bg_recalc_pool_t;
-
- recalc_pool = UT_NEW(recalc_pool_t(recalc_pool_allocator_t(key)), key);
-
- recalc_pool->reserve(RECALC_POOL_INITIAL_SLOTS);
- */
- recalc_pool = new std::vector<table_id_t, recalc_pool_allocator_t>();
-}
+static recalc_pool_t recalc_pool;
+/** Whether the global data structures have been initialized */
+static bool stats_initialised;
/*****************************************************************//**
Free the resources occupied by the recalc pool, called once during
thread de-initialization. */
-static
-void
-dict_stats_recalc_pool_deinit()
-/*===========================*/
+static void dict_stats_recalc_pool_deinit()
{
ut_ad(!srv_read_only_mode);
- recalc_pool->clear();
-
- UT_DELETE(recalc_pool);
- recalc_pool = NULL;
+ recalc_pool.clear();
+ defrag_pool.clear();
+ /*
+ recalc_pool may still have its buffer allocated. It will free it when
+ its destructor is called.
+ The problem is, memory leak detector is run before the recalc_pool's
+ destructor is invoked, and will report recalc_pool's buffer as leaked
+ memory. To avoid that, we force recalc_pool to surrender its buffer
+ to empty_pool object, which will free it when leaving this function:
+ */
+ recalc_pool_t recalc_empty_pool;
+ defrag_pool_t defrag_empty_pool;
+ recalc_pool.swap(recalc_empty_pool);
+ defrag_pool.swap(defrag_empty_pool);
}
/*****************************************************************//**
@@ -130,8 +126,8 @@ dict_stats_recalc_pool_add(
mutex_enter(&recalc_pool_mutex);
/* quit if already in the list */
- for (recalc_pool_iterator_t iter = recalc_pool->begin();
- iter != recalc_pool->end();
+ for (recalc_pool_iterator_t iter = recalc_pool.begin();
+ iter != recalc_pool.end();
++iter) {
if (*iter == table->id) {
@@ -140,18 +136,25 @@ dict_stats_recalc_pool_add(
}
}
- recalc_pool->push_back(table->id);
+ recalc_pool.push_back(table->id);
mutex_exit(&recalc_pool_mutex);
os_event_set(dict_stats_event);
}
+#ifdef WITH_WSREP
+/** Update the table modification counter and if necessary,
+schedule new estimates for table and index statistics to be calculated.
+@param[in,out] table persistent or temporary table
+@param[in] thd current session */
+void dict_stats_update_if_needed(dict_table_t* table, THD* thd)
+#else
/** Update the table modification counter and if necessary,
schedule new estimates for table and index statistics to be calculated.
@param[in,out] table persistent or temporary table */
-void
-dict_stats_update_if_needed(dict_table_t* table)
+void dict_stats_update_if_needed_func(dict_table_t* table)
+#endif
{
ut_ad(table->stat_initialized);
ut_ad(!mutex_own(&dict_sys->mutex));
@@ -163,6 +166,15 @@ dict_stats_update_if_needed(dict_table_t* table)
if (counter > n_rows / 10 /* 10% */
&& dict_stats_auto_recalc_is_enabled(table)) {
+#ifdef WITH_WSREP
+ if (thd && wsrep_on(thd) && wsrep_thd_is_BF(thd, 0)) {
+ WSREP_DEBUG("Avoiding background statistics"
+ " calculation for table %s",
+ table->name.m_name);
+ return;
+ }
+#endif /* WITH_WSREP */
+
dict_stats_recalc_pool_add(table);
table->stat_modified_counter = 0;
}
@@ -200,14 +212,14 @@ dict_stats_recalc_pool_get(
mutex_enter(&recalc_pool_mutex);
- if (recalc_pool->empty()) {
+ if (recalc_pool.empty()) {
mutex_exit(&recalc_pool_mutex);
return(false);
}
- *id = recalc_pool->at(0);
+ *id = recalc_pool.at(0);
- recalc_pool->erase(recalc_pool->begin());
+ recalc_pool.erase(recalc_pool.begin());
mutex_exit(&recalc_pool_mutex);
@@ -229,13 +241,13 @@ dict_stats_recalc_pool_del(
ut_ad(table->id > 0);
- for (recalc_pool_iterator_t iter = recalc_pool->begin();
- iter != recalc_pool->end();
+ for (recalc_pool_iterator_t iter = recalc_pool.begin();
+ iter != recalc_pool.end();
++iter) {
if (*iter == table->id) {
/* erase() invalidates the iterator */
- recalc_pool->erase(iter);
+ recalc_pool.erase(iter);
break;
}
}
@@ -274,7 +286,6 @@ dict_stats_thread_init()
dict_stats_event = os_event_create(0);
dict_stats_shutdown_event = os_event_create(0);
-
ut_d(dict_stats_disabled_event = os_event_create(0));
/* The recalc_pool_mutex is acquired from:
@@ -293,9 +304,8 @@ dict_stats_thread_init()
mutex_create(LATCH_ID_RECALC_POOL, &recalc_pool_mutex);
- dict_stats_recalc_pool_init();
dict_defrag_pool_init();
-
+ stats_initialised = true;
}
/*****************************************************************//**
@@ -308,10 +318,12 @@ dict_stats_thread_deinit()
ut_a(!srv_read_only_mode);
ut_ad(!srv_dict_stats_thread_active);
- if (recalc_pool == NULL) {
+ if (!stats_initialised) {
return;
}
+ stats_initialised = false;
+
dict_stats_recalc_pool_deinit();
dict_defrag_pool_deinit();
diff --git a/storage/innobase/fts/fts0ast.cc b/storage/innobase/fts/fts0ast.cc
index 82c4438196b..d6695cec5be 100644
--- a/storage/innobase/fts/fts0ast.cc
+++ b/storage/innobase/fts/fts0ast.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
-Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2018, 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
@@ -28,6 +29,7 @@ Created 2007/3/16 Sunny Bains.
#include "fts0ast.h"
#include "fts0pars.h"
#include "fts0fts.h"
+#include "row0sel.h"
/* The FTS ast visit pass. */
enum fts_ast_visit_pass_t {
@@ -602,6 +604,7 @@ fts_ast_visit(
bool revisit = false;
bool will_be_ignored = false;
fts_ast_visit_pass_t visit_pass = FTS_PASS_FIRST;
+ const trx_t* trx = node->trx;
start_node = node->list.head;
@@ -700,6 +703,10 @@ fts_ast_visit(
}
}
+ if (trx_is_interrupted(trx)) {
+ return DB_INTERRUPTED;
+ }
+
if (revisit) {
/* Exist pass processes the skipped FTS_EXIST operation. */
for (node = start_node;
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index d874725c374..7c26614b309 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -202,7 +202,7 @@ FTS auxiliary INDEX table and clear the cache at the end.
@param[in,out] sync sync state
@param[in] unlock_cache whether unlock cache lock when write node
@param[in] wait whether wait when a sync is in progress
-@param[in] has_dict whether has dict operation lock
+@param[in] has_dict whether has dict operation lock
@return DB_SUCCESS if all OK */
static
dberr_t
@@ -860,37 +860,28 @@ fts_drop_index(
err = fts_drop_index_tables(trx, index);
- for(;;) {
- bool retry = false;
- if (index->index_fts_syncing) {
- retry = true;
- }
- if (!retry){
- fts_free(table);
- break;
- }
+ while (index->index_fts_syncing
+ && !trx_is_interrupted(trx)) {
DICT_BG_YIELD(trx);
}
+
+ fts_free(table);
+
return(err);
}
- for(;;) {
- bool retry = false;
- if (index->index_fts_syncing) {
- retry = true;
- }
- if (!retry){
- current_doc_id = table->fts->cache->next_doc_id;
- first_doc_id = table->fts->cache->first_doc_id;
- fts_cache_clear(table->fts->cache);
- fts_cache_destroy(table->fts->cache);
- table->fts->cache = fts_cache_create(table);
- table->fts->cache->next_doc_id = current_doc_id;
- table->fts->cache->first_doc_id = first_doc_id;
- break;
- }
+ while (index->index_fts_syncing
+ && !trx_is_interrupted(trx)) {
DICT_BG_YIELD(trx);
}
+
+ current_doc_id = table->fts->cache->next_doc_id;
+ first_doc_id = table->fts->cache->first_doc_id;
+ fts_cache_clear(table->fts->cache);
+ fts_cache_destroy(table->fts->cache);
+ table->fts->cache = fts_cache_create(table);
+ table->fts->cache->next_doc_id = current_doc_id;
+ table->fts->cache->first_doc_id = first_doc_id;
} else {
fts_cache_t* cache = table->fts->cache;
fts_index_cache_t* index_cache;
@@ -900,18 +891,14 @@ fts_drop_index(
index_cache = fts_find_index_cache(cache, index);
if (index_cache != NULL) {
- for(;;) {
- bool retry = false;
- if (index->index_fts_syncing) {
- retry = true;
- }
- if (!retry && index_cache->words) {
- fts_words_free(index_cache->words);
- rbt_free(index_cache->words);
- break;
- }
+ while (index->index_fts_syncing
+ && !trx_is_interrupted(trx)) {
DICT_BG_YIELD(trx);
}
+ if (index_cache->words) {
+ fts_words_free(index_cache->words);
+ rbt_free(index_cache->words);
+ }
ib_vector_remove(cache->indexes, *(void**) index_cache);
}
@@ -4048,6 +4035,9 @@ fts_sync_write_words(
word = rbt_value(fts_tokenizer_word_t, rbt_node);
+ DBUG_EXECUTE_IF("fts_instrument_write_words_before_select_index",
+ os_thread_sleep(300000););
+
selected = fts_select_index(
index_cache->charset, word->text.f_str,
word->text.f_len);
@@ -4332,7 +4322,7 @@ FTS auxiliary INDEX table and clear the cache at the end.
@param[in,out] sync sync state
@param[in] unlock_cache whether unlock cache lock when write node
@param[in] wait whether wait when a sync is in progress
-@param[in] has_dict whether has dict operation lock
+@param[in] has_dict whether has dict operation lock
@return DB_SUCCESS if all OK */
static
dberr_t
@@ -4398,15 +4388,13 @@ begin_sync:
continue;
}
+ DBUG_EXECUTE_IF("fts_instrument_sync_before_syncing",
+ os_thread_sleep(300000););
index_cache->index->index_fts_syncing = true;
- DBUG_EXECUTE_IF("fts_instrument_sync_sleep_drop_waits",
- os_thread_sleep(10000000);
- );
error = fts_sync_index(sync, index_cache);
- if (error != DB_SUCCESS && !sync->interrupted) {
-
+ if (error != DB_SUCCESS) {
goto end_sync;
}
}
@@ -4441,8 +4429,8 @@ end_sync:
}
rw_lock_x_lock(&cache->lock);
- /* Clear fts syncing flags of any indexes incase sync is
- interrupeted */
+ /* Clear fts syncing flags of any indexes in case sync is
+ interrupted */
for (i = 0; i < ib_vector_size(cache->indexes); ++i) {
static_cast<fts_index_cache_t*>(
ib_vector_get(cache->indexes, i))
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index 4d93451a40d..77115049903 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -62,12 +62,6 @@ static const ulint FTS_WORD_NODES_INIT_SIZE = 64;
/** Last time we did check whether system need a sync */
static ib_time_t last_check_sync_time;
-#if 0
-/** Check each table in round robin to see whether they'd
-need to be "optimized" */
-static ulint fts_optimize_sync_iterator = 0;
-#endif
-
/** State of a table within the optimization sub system. */
enum fts_state_t {
FTS_STATE_LOADED,
@@ -79,17 +73,11 @@ enum fts_state_t {
/** FTS optimize thread message types. */
enum fts_msg_type_t {
- FTS_MSG_START, /*!< Start optimizing thread */
-
- FTS_MSG_PAUSE, /*!< Pause optimizing thread */
-
FTS_MSG_STOP, /*!< Stop optimizing and exit thread */
FTS_MSG_ADD_TABLE, /*!< Add table to the optimize thread's
work queue */
- FTS_MSG_OPTIMIZE_TABLE, /*!< Optimize a table */
-
FTS_MSG_DEL_TABLE, /*!< Remove a table from the optimize
threads work queue */
FTS_MSG_SYNC_TABLE /*!< Sync fts cache of a table */
@@ -234,7 +222,7 @@ struct fts_msg_t {
/** The number of words to read and optimize in a single pass. */
ulong fts_num_word_optimize;
-// FIXME
+/** Whether to enable additional FTS diagnostic printout. */
char fts_enable_diag_print;
/** ZLib compressed block size.*/
@@ -2554,12 +2542,9 @@ fts_optimize_create_msg(
return(msg);
}
-/**********************************************************************//**
-Add the table to add to the OPTIMIZER's list. */
-void
-fts_optimize_add_table(
-/*===================*/
- dict_table_t* table) /*!< in: table to add */
+/** Add the table to add to the OPTIMIZER's list.
+@param[in] table table to add */
+void fts_optimize_add_table(dict_table_t* table)
{
fts_msg_t* msg;
@@ -2575,28 +2560,6 @@ fts_optimize_add_table(
ib_wqueue_add(fts_optimize_wq, msg, msg->heap);
}
-#if 0
-/**********************************************************************//**
-Optimize a table. */
-static
-void
-fts_optimize_do_table(
-/*==================*/
- dict_table_t* table) /*!< in: table to optimize */
-{
- fts_msg_t* msg;
-
- /* Optimizer thread could be shutdown */
- if (!fts_optimize_wq) {
- return;
- }
-
- msg = fts_optimize_create_msg(FTS_MSG_OPTIMIZE_TABLE, table);
-
- ib_wqueue_add(fts_optimize_wq, msg, msg->heap);
-}
-#endif
-
/**********************************************************************//**
Remove the table from the OPTIMIZER's list. We do wait for
acknowledgement from the consumer of the message. */
@@ -2672,53 +2635,6 @@ fts_optimize_request_sync_table(
}
/**********************************************************************//**
-Find the slot for a particular table.
-@return slot if found else NULL. */
-static
-fts_slot_t*
-fts_optimize_find_slot(
-/*===================*/
- ib_vector_t* tables, /*!< in: vector of tables */
- const dict_table_t* table) /*!< in: table to add */
-{
- ulint i;
-
- for (i = 0; i < ib_vector_size(tables); ++i) {
- fts_slot_t* slot;
-
- slot = static_cast<fts_slot_t*>(ib_vector_get(tables, i));
-
- if (slot->table == table) {
- return(slot);
- }
- }
-
- return(NULL);
-}
-
-/**********************************************************************//**
-Start optimizing table. */
-static
-void
-fts_optimize_start_table(
-/*=====================*/
- ib_vector_t* tables, /*!< in/out: vector of tables */
- dict_table_t* table) /*!< in: table to optimize */
-{
- fts_slot_t* slot;
-
- slot = fts_optimize_find_slot(tables, table);
-
- if (slot == NULL) {
- ib::error() << "Table " << table->name << " not registered"
- " with the optimize thread.";
- } else {
- slot->last_run = 0;
- slot->completed = 0;
- }
-}
-
-/**********************************************************************//**
Add the table to the vector if it doesn't already exist. */
static
ibool
@@ -2900,57 +2816,6 @@ fts_is_sync_needed(
return(false);
}
-#if 0
-/*********************************************************************//**
-Check whether a table needs to be optimized. */
-static
-void
-fts_optimize_need_sync(
-/*===================*/
- ib_vector_t* tables) /*!< in: list of tables */
-{
- dict_table_t* table = NULL;
- fts_slot_t* slot;
- ulint num_table = ib_vector_size(tables);
-
- if (!num_table) {
- return;
- }
-
- if (fts_optimize_sync_iterator >= num_table) {
- fts_optimize_sync_iterator = 0;
- }
-
- slot = ib_vector_get(tables, fts_optimize_sync_iterator);
- table = slot->table;
-
- if (!table) {
- return;
- }
-
- ut_ad(table->fts);
-
- if (table->fts->cache) {
- ulint deleted = table->fts->cache->deleted;
-
- if (table->fts->cache->added
- >= fts_optimize_add_threshold) {
- fts_sync_table(table);
- } else if (deleted >= fts_optimize_delete_threshold) {
- fts_optimize_do_table(table);
-
- mutex_enter(&table->fts->cache->deleted_lock);
- table->fts->cache->deleted -= deleted;
- mutex_exit(&table->fts->cache->deleted_lock);
- }
- }
-
- fts_optimize_sync_iterator++;
-
- return;
-}
-#endif
-
/** Sync fts cache of a table
@param[in] table_id table id */
void
@@ -2963,7 +2828,7 @@ fts_optimize_sync_table(
if (table) {
if (dict_table_has_fts_index(table) && table->fts->cache) {
- fts_sync_table(table, true, false, true);
+ fts_sync_table(table, true, false, false);
}
dict_table_close(table, FALSE, FALSE);
@@ -3031,8 +2896,7 @@ DECLARE_THREAD(fts_optimize_thread)(
fts_msg_t* msg;
msg = static_cast<fts_msg_t*>(
- ib_wqueue_timedwait(wq,
- FTS_QUEUE_WAIT_IN_USECS));
+ ib_wqueue_timedwait(wq, FTS_QUEUE_WAIT_IN_USECS));
/* Timeout ? */
if (msg == NULL) {
@@ -3044,12 +2908,6 @@ DECLARE_THREAD(fts_optimize_thread)(
}
switch (msg->type) {
- case FTS_MSG_START:
- break;
-
- case FTS_MSG_PAUSE:
- break;
-
case FTS_MSG_STOP:
done = TRUE;
break;
@@ -3064,15 +2922,6 @@ DECLARE_THREAD(fts_optimize_thread)(
}
break;
- case FTS_MSG_OPTIMIZE_TABLE:
- if (!done) {
- fts_optimize_start_table(
- fts_slots,
- static_cast<dict_table_t*>(
- msg->ptr));
- }
- break;
-
case FTS_MSG_DEL_TABLE:
if (fts_optimize_del_table(
fts_slots, static_cast<fts_msg_del_t*>(
@@ -3087,6 +2936,10 @@ DECLARE_THREAD(fts_optimize_thread)(
break;
case FTS_MSG_SYNC_TABLE:
+ DBUG_EXECUTE_IF(
+ "fts_instrument_msg_sync_sleep",
+ os_thread_sleep(300000););
+
fts_optimize_sync_table(
*static_cast<table_id_t*>(msg->ptr));
break;
@@ -3149,7 +3002,7 @@ fts_optimize_init(void)
ut_ad(!srv_read_only_mode);
/* For now we only support one optimize thread. */
- ut_a(fts_optimize_wq == NULL);
+ ut_a(!fts_optimize_wq);
/* Create FTS optimize work queue */
fts_optimize_wq = ib_wqueue_create();
diff --git a/storage/innobase/fts/fts0pars.cc b/storage/innobase/fts/fts0pars.cc
index e4d1bba2be6..56cc8d6052c 100644
--- a/storage/innobase/fts/fts0pars.cc
+++ b/storage/innobase/fts/fts0pars.cc
@@ -88,7 +88,7 @@ extern int fts_lexer(YYSTYPE*, fts_lexer_t*);
extern int fts_blexer(YYSTYPE*, yyscan_t);
extern int fts_tlexer(YYSTYPE*, yyscan_t);
-typedef int (*fts_scan)();
+
extern int ftserror(const char* p);
@@ -103,8 +103,8 @@ extern int ftserror(const char* p);
#define YYTOKENFREE(token) fts_ast_string_free((token))
-typedef int (*fts_scanner_alt)(YYSTYPE* val, yyscan_t yyscanner);
-typedef int (*fts_scanner)();
+
+typedef int (*fts_scanner)(YYSTYPE* val, yyscan_t yyscanner);
struct fts_lexer_t {
fts_scanner scanner;
@@ -1948,7 +1948,7 @@ fts_lexer_create(
reinterpret_cast<const char*>(query),
static_cast<int>(query_len),
fts_lexer->yyscanner);
- fts_lexer->scanner = reinterpret_cast<fts_scan>(fts_blexer);
+ fts_lexer->scanner = fts_blexer;
/* FIXME: Debugging */
/* fts0bset_debug(1 , fts_lexer->yyscanner); */
} else {
@@ -1957,7 +1957,7 @@ fts_lexer_create(
reinterpret_cast<const char*>(query),
static_cast<int>(query_len),
fts_lexer->yyscanner);
- fts_lexer->scanner = reinterpret_cast<fts_scan>(fts_tlexer);
+ fts_lexer->scanner = fts_tlexer;
}
return(fts_lexer);
@@ -1971,7 +1971,7 @@ fts_lexer_free(
/*===========*/
fts_lexer_t* fts_lexer)
{
- if (fts_lexer->scanner == (fts_scan) fts_blexer) {
+ if (fts_lexer->scanner == fts_blexer) {
fts0blex_destroy(fts_lexer->yyscanner);
} else {
fts0tlex_destroy(fts_lexer->yyscanner);
@@ -1988,9 +1988,9 @@ fts_lexer(
YYSTYPE* val,
fts_lexer_t* fts_lexer)
{
- fts_scanner_alt func_ptr;
+ fts_scanner func_ptr;
- func_ptr = (fts_scanner_alt) fts_lexer->scanner;
+ func_ptr = fts_lexer->scanner;
return(func_ptr(val, fts_lexer->yyscanner));
}
diff --git a/storage/innobase/fts/fts0pars.y b/storage/innobase/fts/fts0pars.y
index 1f4ec9922e3..4db72ca65ad 100644
--- a/storage/innobase/fts/fts0pars.y
+++ b/storage/innobase/fts/fts0pars.y
@@ -36,7 +36,7 @@ extern int fts_lexer(YYSTYPE*, fts_lexer_t*);
extern int fts_blexer(YYSTYPE*, yyscan_t);
extern int fts_tlexer(YYSTYPE*, yyscan_t);
-typedef int (*fts_scan)();
+
extern int ftserror(const char* p);
@@ -49,8 +49,8 @@ extern int ftserror(const char* p);
#define YYPARSE_PARAM state
#define YYLEX_PARAM ((fts_ast_state_t*) state)->lexer
-typedef int (*fts_scanner_alt)(YYSTYPE* val, yyscan_t yyscanner);
-typedef int (*fts_scanner)();
+
+typedef int (*fts_scanner)(YYSTYPE* val, yyscan_t yyscanner);
struct fts_lexer_struct {
fts_scanner scanner;
@@ -238,13 +238,13 @@ fts_lexer_create(
if (boolean_mode) {
fts0blex_init(&fts_lexer->yyscanner);
fts0b_scan_bytes((char*) query, (int) query_len, fts_lexer->yyscanner);
- fts_lexer->scanner = (fts_scan) fts_blexer;
+ fts_lexer->scanner = fts_blexer;
/* FIXME: Debugging */
/* fts0bset_debug(1 , fts_lexer->yyscanner); */
} else {
fts0tlex_init(&fts_lexer->yyscanner);
fts0t_scan_bytes((char*) query, (int) query_len, fts_lexer->yyscanner);
- fts_lexer->scanner = (fts_scan) fts_tlexer;
+ fts_lexer->scanner = fts_tlexer;
}
return(fts_lexer);
@@ -258,7 +258,7 @@ fts_lexer_free(
/*===========*/
fts_lexer_t* fts_lexer)
{
- if (fts_lexer->scanner == (fts_scan) fts_blexer) {
+ if (fts_lexer->scanner == fts_blexer) {
fts0blex_destroy(fts_lexer->yyscanner);
} else {
fts0tlex_destroy(fts_lexer->yyscanner);
@@ -275,9 +275,9 @@ fts_lexer(
YYSTYPE* val,
fts_lexer_t* fts_lexer)
{
- fts_scanner_alt func_ptr;
+ fts_scanner func_ptr;
- func_ptr = (fts_scanner_alt) fts_lexer->scanner;
+ func_ptr = fts_lexer->scanner;
return(func_ptr(val, fts_lexer->yyscanner));
}
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc
index 6a0496bedcd..5ae8e28974e 100644
--- a/storage/innobase/fts/fts0que.cc
+++ b/storage/innobase/fts/fts0que.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -3920,6 +3920,7 @@ fts_query_can_optimize(
}
/** FTS Query entry point.
+@param[in,out] trx transaction
@param[in] index fts index to search
@param[in] flags FTS search mode
@param[in] query_str FTS query
@@ -3928,6 +3929,7 @@ fts_query_can_optimize(
@return DB_SUCCESS if successful otherwise error code */
dberr_t
fts_query(
+ trx_t* trx,
dict_index_t* index,
uint flags,
const byte* query_str,
@@ -3940,7 +3942,7 @@ fts_query(
ulint lc_query_str_len;
ulint result_len;
bool boolean_mode;
- trx_t* query_trx;
+ trx_t* query_trx; /* FIXME: use provided trx */
CHARSET_INFO* charset;
ulint start_time_ms;
bool will_be_ignored = false;
@@ -4055,6 +4057,7 @@ fts_query(
/* Parse the input query string. */
if (fts_query_parse(&query, lc_query_str, result_len)) {
fts_ast_node_t* ast = query.root;
+ ast->trx = trx;
/* Optimize query to check if it's a single term */
fts_query_can_optimize(&query, flags);
@@ -4068,6 +4071,11 @@ fts_query(
query.error = fts_ast_visit(
FTS_NONE, ast, fts_query_visitor,
&query, &will_be_ignored);
+ if (query.error == DB_INTERRUPTED) {
+ error = DB_INTERRUPTED;
+ ut_free(lc_query_str);
+ goto func_exit;
+ }
/* If query expansion is requested, extend the search
with first search pass result */
@@ -4094,6 +4102,15 @@ fts_query(
ut_zalloc_nokey(sizeof(**result)));
}
+ if (trx_is_interrupted(trx)) {
+ error = DB_INTERRUPTED;
+ ut_free(lc_query_str);
+ if (*result) {
+ fts_query_free_result(*result);
+ }
+ goto func_exit;
+ }
+
ut_free(lc_query_str);
if (fts_enable_diag_print && (*result)) {
diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc
index eac904e5b24..146d1616347 100644
--- a/storage/innobase/gis/gis0rtree.cc
+++ b/storage/innobase/gis/gis0rtree.cc
@@ -658,7 +658,7 @@ rtr_adjust_upper_level(
/* Create a memory heap where the data tuple is stored */
heap = mem_heap_create(1024);
- memset(&cursor, 0, sizeof(cursor));
+ cursor.init();
cursor.thr = sea_cur->thr;
@@ -1367,7 +1367,7 @@ rtr_ins_enlarge_mbr(
rtr_page_cal_mbr(index, block, &new_mbr, heap);
/* Get father block. */
- memset(&cursor, 0, sizeof(cursor));
+ cursor.init();
offsets = rtr_page_get_father_block(
NULL, heap, index, block, mtr, btr_cur, &cursor);
diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc
index 67b2feb7af6..b137a768830 100644
--- a/storage/innobase/gis/gis0sea.cc
+++ b/storage/innobase/gis/gis0sea.cc
@@ -1546,7 +1546,7 @@ rtr_copy_buf(
will be copied. It is also undefined what will happen with the
newly memcpy()ed mutex if the source mutex was acquired by
(another) thread while it was copied. */
- memcpy(&matches->block.page, &block->page, sizeof(buf_page_t));
+ new (&matches->block.page) buf_page_t(block->page);
matches->block.frame = block->frame;
matches->block.unzip_LRU = block->unzip_LRU;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 2b7c700dd55..e2b61b627de 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -5324,15 +5324,16 @@ ha_innobase::max_supported_key_length() const
switch (srv_page_size) {
case 4096:
- return(768);
+ /* Hack: allow mysql.innodb_index_stats to be created. */
+ /* FIXME: rewrite this API, and in sql_table.cc consider
+ that in index-organized tables (such as InnoDB), secondary
+ index records will be padded with the PRIMARY KEY, instead
+ of some short ROWID or record heap address. */
+ return(1173);
case 8192:
return(1536);
default:
-#ifdef WITH_WSREP
- return(3500);
-#else
return(3500);
-#endif
}
}
@@ -10071,8 +10072,7 @@ ha_innobase::ft_init_ext(
const_cast<char*>(query));
// FIXME: support ft_init_ext_with_hints(), pass LIMIT
- // FIXME: use trx
- dberr_t error = fts_query(index, flags, q, query_len, &result);
+ dberr_t error = fts_query(trx, index, flags, q, query_len, &result);
if (error != DB_SUCCESS) {
my_error(convert_error_code_to_mysql(error, 0, NULL), MYF(0));
@@ -13266,6 +13266,36 @@ innobase_rename_table(
row_mysql_lock_data_dictionary(trx);
+ dict_table_t* table = dict_table_open_on_name(norm_from, TRUE, FALSE,
+ DICT_ERR_IGNORE_NONE);
+
+ /* Since DICT_BG_YIELD has sleep for 250 milliseconds,
+ Convert lock_wait_timeout unit from second to 250 milliseconds */
+ long int lock_wait_timeout = thd_lock_wait_timeout(trx->mysql_thd) * 4;
+ if (table != NULL) {
+ for (dict_index_t* index = dict_table_get_first_index(table);
+ index != NULL;
+ index = dict_table_get_next_index(index)) {
+
+ if (index->type & DICT_FTS) {
+ /* Found */
+ while (index->index_fts_syncing
+ && !trx_is_interrupted(trx)
+ && (lock_wait_timeout--) > 0) {
+ DICT_BG_YIELD(trx);
+ }
+ }
+ }
+ dict_table_close(table, TRUE, FALSE);
+ }
+
+ /* FTS sync is in progress. We shall timeout this operation */
+ if (lock_wait_timeout < 0) {
+ error = DB_LOCK_WAIT_TIMEOUT;
+ row_mysql_unlock_data_dictionary(trx);
+ DBUG_RETURN(error);
+ }
+
error = row_rename_table_for_mysql(norm_from, norm_to, trx, TRUE);
if (error != DB_SUCCESS) {
@@ -13395,6 +13425,10 @@ ha_innobase::rename_table(
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to);
error = DB_ERROR;
+ } else if (error == DB_LOCK_WAIT_TIMEOUT) {
+ my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0), to);
+
+ error = DB_LOCK_WAIT;
}
DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 3f251b2f6f6..a8cbee11c8e 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -9431,24 +9431,24 @@ ha_innobase::commit_inplace_alter_table(
trx_t* trx = ctx0->trx;
bool fail = false;
- if (new_clustered) {
- for (inplace_alter_handler_ctx** pctx = ctx_array;
- *pctx; pctx++) {
- ha_innobase_inplace_ctx* ctx
- = static_cast<ha_innobase_inplace_ctx*>(*pctx);
- DBUG_ASSERT(ctx->need_rebuild());
+ /* Stop background FTS operations. */
+ for (inplace_alter_handler_ctx** pctx = ctx_array;
+ *pctx; pctx++) {
+ ha_innobase_inplace_ctx* ctx
+ = static_cast<ha_innobase_inplace_ctx*>(*pctx);
+
+ DBUG_ASSERT(new_clustered == ctx->need_rebuild());
+ if (new_clustered) {
if (ctx->old_table->fts) {
ut_ad(!ctx->old_table->fts->add_wq);
- fts_optimize_remove_table(
- ctx->old_table);
+ fts_optimize_remove_table(ctx->old_table);
}
+ }
- if (ctx->new_table->fts) {
- ut_ad(!ctx->new_table->fts->add_wq);
- fts_optimize_remove_table(
- ctx->new_table);
- }
+ if (ctx->new_table->fts) {
+ ut_ad(!ctx->new_table->fts->add_wq);
+ fts_optimize_remove_table(ctx->new_table);
}
}
@@ -9495,41 +9495,39 @@ ha_innobase::commit_inplace_alter_table(
/* Make a concurrent Drop fts Index to wait until sync of that
fts index is happening in the background */
- for (;;) {
+ for (int retry_count = 0;;) {
bool retry = false;
for (inplace_alter_handler_ctx** pctx = ctx_array;
*pctx; pctx++) {
- int count =0;
ha_innobase_inplace_ctx* ctx
= static_cast<ha_innobase_inplace_ctx*>(*pctx);
DBUG_ASSERT(new_clustered == ctx->need_rebuild());
if (dict_fts_index_syncing(ctx->old_table)) {
- count++;
- if (count == 100) {
- fprintf(stderr,
- "Drop index waiting for background sync"
- "to finish\n");
- }
retry = true;
+ break;
}
if (new_clustered && dict_fts_index_syncing(ctx->new_table)) {
- count++;
- if (count == 100) {
- fprintf(stderr,
- "Drop index waiting for background sync"
- "to finish\n");
- }
retry = true;
+ break;
}
}
- if (!retry) {
+ if (!retry) {
break;
}
+ /* Print a message if waiting for a long time. */
+ if (retry_count < 100) {
+ retry_count++;
+ } else {
+ ib::info() << "Drop index waiting for background sync"
+ " to finish";
+ retry_count = 0;
+ }
+
DICT_BG_YIELD(trx);
}
@@ -9806,6 +9804,11 @@ foreign_fail:
ut_a(fts_check_cached_index(ctx->old_table));
DBUG_INJECT_CRASH("ib_commit_inplace_crash_fail",
crash_fail_inject_count++);
+
+ /* Restart the FTS background operations. */
+ if (ctx->old_table->fts) {
+ fts_optimize_add_table(ctx->old_table);
+ }
}
row_mysql_unlock_data_dictionary(trx);
@@ -9889,8 +9892,6 @@ foreign_fail:
(*pctx);
DBUG_ASSERT(ctx->need_rebuild() == new_clustered);
- bool add_fts = false;
-
/* Publish the created fulltext index, if any.
Note that a fulltext index can be created without
creating the clustered index, if there already exists
@@ -9905,14 +9906,14 @@ foreign_fail:
is left unset when a drop proceeds the add. */
DICT_TF2_FLAG_SET(ctx->new_table, DICT_TF2_FTS);
fts_add_index(index, ctx->new_table);
- add_fts = true;
}
}
ut_d(dict_table_check_for_dup_indexes(
ctx->new_table, CHECK_ALL_COMPLETE));
- if (add_fts) {
+ /* Start/Restart the FTS background operations. */
+ if (ctx->new_table->fts) {
fts_optimize_add_table(ctx->new_table);
}
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index 25dd9e9993d..f0df1bc9839 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -1359,12 +1359,14 @@ i_s_cmp_fill_low(
page0zip.cc. */
table->field[1]->store(zip_stat->compressed, true);
table->field[2]->store(zip_stat->compressed_ok, true);
- table->field[3]->store(zip_stat->compressed_usec / 1000000, true);
+ table->field[3]->store(zip_stat->compressed_usec / 1000000,
+ true);
table->field[4]->store(zip_stat->decompressed, true);
- table->field[5]->store(zip_stat->decompressed_usec / 1000000, true);
+ table->field[5]->store(zip_stat->decompressed_usec / 1000000,
+ true);
if (reset) {
- memset(zip_stat, 0, sizeof *zip_stat);
+ new (zip_stat) page_zip_stat_t();
}
if (schema_table_store_record(thd, table)) {
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index dc1f6dd82d8..f87370be70c 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -955,6 +955,26 @@ struct btr_cur_t {
rtr_info_t* rtr_info; /*!< rtree search info */
btr_cur_t():thr(NULL), rtr_info(NULL) {}
/* default values */
+ /** Zero-initialize all fields */
+ void init()
+ {
+ index = NULL;
+ memset(&page_cur, 0, sizeof page_cur);
+ purge_node = NULL;
+ left_block = NULL;
+ thr = NULL;
+ flag = btr_cur_method(0);
+ tree_height = 0;
+ up_match = 0;
+ up_bytes = 0;
+ low_match = 0;
+ low_bytes = 0;
+ n_fields = 0;
+ n_bytes = 0;
+ fold = 0;
+ path_arr = NULL;
+ rtr_info = NULL;
+ }
};
/******************************************************//**
diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h
index f478d3fa876..747ad676e33 100644
--- a/storage/innobase/include/btr0pcur.h
+++ b/storage/innobase/include/btr0pcur.h
@@ -538,6 +538,18 @@ struct btr_pcur_t{
/** old_rec_buf size if old_rec_buf is not NULL */
ulint buf_size;
+ btr_pcur_t() :
+ btr_cur(), latch_mode(0), old_stored(false), old_rec(NULL),
+ old_n_fields(0), rel_pos(btr_pcur_pos_t(0)),
+ block_when_stored(NULL),
+ modify_clock(0), withdraw_clock(0),
+ pos_state(BTR_PCUR_NOT_POSITIONED),
+ search_mode(PAGE_CUR_UNSUPP), trx_if_known(NULL),
+ old_rec_buf(NULL), buf_size(0)
+ {
+ btr_cur.init();
+ }
+
/** Return the index of this persistent cursor */
dict_index_t* index() const { return(btr_cur.index); }
};
diff --git a/storage/innobase/include/dict0defrag_bg.h b/storage/innobase/include/dict0defrag_bg.h
index 8d77a461dc9..ddef139853c 100644
--- a/storage/innobase/include/dict0defrag_bg.h
+++ b/storage/innobase/include/dict0defrag_bg.h
@@ -33,6 +33,25 @@ Created 25/08/2016 Jan Lindström
#include "os0event.h"
#include "os0thread.h"
+
+/** 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;
+
+/** Pool where we store information on which tables are to be processed
+by background defragmentation. */
+extern defrag_pool_t defrag_pool;
+
/*****************************************************************//**
Initialize the defrag pool, called once during thread initialization. */
void
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 66b64f96128..3dcf290a276 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -1862,14 +1862,6 @@ const char*
dict_tf_to_row_format_string(
/*=========================*/
ulint table_flag); /*!< in: row format setting */
-/****************************************************************//**
-Return maximum size of the node pointer record.
-@return maximum size of the record in bytes */
-ulint
-dict_index_node_ptr_max_size(
-/*=========================*/
- const dict_index_t* index) /*!< in: index */
- MY_ATTRIBUTE((warn_unused_result));
/** encode number of columns and number of virtual columns in one
4 bytes value. We could do this because the number of columns in
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 8d7c9d47e9f..3e06def55b0 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -771,6 +771,9 @@ struct dict_field_t{
column if smaller than
DICT_ANTELOPE_MAX_INDEX_COL_LEN */
+ /** Zero-initialize all fields */
+ dict_field_t() : col(NULL), name(NULL), prefix_len(0), fixed_len(0) {}
+
/** Check whether two index fields are equivalent.
@param[in] old the other index field
@return whether the index fields are equivalent */
diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h
index 5dd53c46d1b..407e0221110 100644
--- a/storage/innobase/include/dict0stats.h
+++ b/storage/innobase/include/dict0stats.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2009, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2009, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -32,6 +32,9 @@ Created Jan 06, 2010 Vasil Dimov
#include "dict0types.h"
#include "trx0types.h"
+#define TABLE_STATS_NAME "mysql/innodb_table_stats"
+#define INDEX_STATS_NAME "mysql/innodb_index_stats"
+
enum dict_stats_upd_option_t {
DICT_STATS_RECALC_PERSISTENT,/* (re) calculate the
statistics using a precise and slow
@@ -110,12 +113,21 @@ dict_stats_deinit(
dict_table_t* table) /*!< in/out: table */
MY_ATTRIBUTE((nonnull));
+#ifdef WITH_WSREP
+/** Update the table modification counter and if necessary,
+schedule new estimates for table and index statistics to be calculated.
+@param[in,out] table persistent or temporary table
+@param[in] thd current session */
+void dict_stats_update_if_needed(dict_table_t* table, THD* thd)
+ MY_ATTRIBUTE((nonnull(1)));
+#else
/** Update the table modification counter and if necessary,
schedule new estimates for table and index statistics to be calculated.
@param[in,out] table persistent or temporary table */
-void
-dict_stats_update_if_needed(dict_table_t* table)
+void dict_stats_update_if_needed_func(dict_table_t* table)
MY_ATTRIBUTE((nonnull));
+# define dict_stats_update_if_needed(t,thd) dict_stats_update_if_needed_func(t)
+#endif
/*********************************************************************//**
Calculates new estimates for table and index statistics. The statistics
diff --git a/storage/innobase/include/fts0ast.h b/storage/innobase/include/fts0ast.h
index b5187ce2a41..2a2b25c36bd 100644
--- a/storage/innobase/include/fts0ast.h
+++ b/storage/innobase/include/fts0ast.h
@@ -1,6 +1,7 @@
/*****************************************************************************
-Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2016, 2018, 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
@@ -296,6 +297,8 @@ struct fts_ast_node_t {
fts_ast_node_t* next_alloc; /*!< For tracking allocations */
bool visited; /*!< whether this node is
already processed */
+ /** current transaction */
+ const trx_t* trx;
/* Used by plugin parser */
fts_ast_node_t* up_node; /*!< Direct up node */
bool go_up; /*!< Flag if go one level up */
diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h
index be2fe7e040b..068720c1947 100644
--- a/storage/innobase/include/fts0fts.h
+++ b/storage/innobase/include/fts0fts.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -561,6 +561,7 @@ fts_commit(
MY_ATTRIBUTE((warn_unused_result));
/** FTS Query entry point.
+@param[in,out] trx transaction
@param[in] index fts index to search
@param[in] flags FTS search mode
@param[in] query_str FTS query
@@ -569,6 +570,7 @@ fts_commit(
@return DB_SUCCESS if successful otherwise error code */
dberr_t
fts_query(
+ trx_t* trx,
dict_index_t* index,
uint flags,
const byte* query_str,
@@ -711,6 +713,12 @@ fts_drop_index_tables(
dict_index_t* index) /*!< in: Index to drop */
MY_ATTRIBUTE((warn_unused_result));
+/** Add the table to add to the OPTIMIZER's list.
+@param[in] table table to add */
+void
+fts_optimize_add_table(
+ dict_table_t* table);
+
/******************************************************************//**
Remove the table from the OPTIMIZER's list. We do wait for
acknowledgement from the consumer of the message. */
diff --git a/storage/innobase/include/fts0priv.h b/storage/innobase/include/fts0priv.h
index aef6e816461..d045c9d3c72 100644
--- a/storage/innobase/include/fts0priv.h
+++ b/storage/innobase/include/fts0priv.h
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2017, 2018, 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
@@ -512,13 +512,6 @@ fts_get_table_id(
MY_ATTRIBUTE((warn_unused_result));
/******************************************************************//**
-Add the table to add to the OPTIMIZER's list. */
-void
-fts_optimize_add_table(
-/*===================*/
- dict_table_t* table); /*!< in: table to add */
-
-/******************************************************************//**
Construct the prefix name of an FTS table.
@return own: table name, must be freed with ut_free() */
char*
diff --git a/storage/innobase/include/row0ftsort.h b/storage/innobase/include/row0ftsort.h
index 25204895f1a..3ae5d5bc175 100644
--- a/storage/innobase/include/row0ftsort.h
+++ b/storage/innobase/include/row0ftsort.h
@@ -122,6 +122,16 @@ struct fts_tokenize_ctx {
dfield_t sort_field[FTS_NUM_FIELDS_SORT];
/*!< in: sort field */
fts_token_list_t fts_token_list;
+
+ fts_tokenize_ctx() :
+ processed_len(0), init_pos(0), buf_used(0),
+ rows_added(), cached_stopword(NULL), sort_field(),
+ fts_token_list()
+ {
+ memset(rows_added, 0, sizeof rows_added);
+ memset(sort_field, 0, sizeof sort_field);
+ UT_LIST_INIT(fts_token_list, &row_fts_token_t::token_list);
+ }
};
typedef struct fts_tokenize_ctx fts_tokenize_ctx_t;
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index ffa4967b9de..bf1d245a65e 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -41,7 +41,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 7
-#define INNODB_VERSION_BUGFIX 22
+#define INNODB_VERSION_BUGFIX 23
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 4d93f2c449c..461dec3ee29 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -1750,7 +1750,10 @@ lock_rec_enqueue_waiting(
lock_prdt_set_prdt(lock, prdt);
}
- if (const trx_t* victim =
+ if (
+#ifdef UNIV_DEBUG
+ const trx_t* victim =
+#endif
DeadlockChecker::check_and_resolve(lock, trx)) {
ut_ad(victim == trx);
lock_reset_lock_and_trx_wait(lock);
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index c6da047e8c5..208fe356fbe 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -2496,30 +2496,15 @@ os_file_fsync_posix(
os_thread_sleep(200000);
break;
- case EIO:
-
- ++failures;
- ut_a(failures < 1000);
-
- if (!(failures % 100)) {
-
- ib::warn()
- << "fsync(): "
- << "An error occurred during "
- << "synchronization,"
- << " retrying";
- }
-
- /* 0.2 sec */
- os_thread_sleep(200000);
- break;
-
case EINTR:
++failures;
ut_a(failures < 2000);
break;
+ case EIO:
+ ib::error() << "fsync() returned EIO, aborting";
+ /* fall through */
default:
ut_error;
break;
@@ -3325,7 +3310,8 @@ os_file_get_status_posix(
{
int ret = stat(path, statinfo);
- if (ret && (errno == ENOENT || errno == ENOTDIR)) {
+ if (ret && (errno == ENOENT || errno == ENOTDIR
+ || errno == ENAMETOOLONG)) {
/* file does not exist */
return(DB_NOT_FOUND);
@@ -4665,7 +4651,8 @@ os_file_get_status_win32(
{
int ret = _stat64(path, statinfo);
- if (ret && (errno == ENOENT || errno == ENOTDIR)) {
+ if (ret && (errno == ENOENT || errno == ENOTDIR
+ || errno == ENAMETOOLONG)) {
/* file does not exist */
return(DB_NOT_FOUND);
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index 4341886d775..a351a1ae01b 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -805,7 +805,6 @@ DECLARE_THREAD(fts_parallel_tokenization)(
merge_file = psort_info->merge_file;
blob_heap = mem_heap_create(512);
memset(&doc, 0, sizeof(doc));
- memset(&t_ctx, 0, sizeof(t_ctx));
memset(mycount, 0, FTS_NUM_AUX_INDEX * sizeof(int));
doc.charset = fts_index_get_charset(
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index 0357804f617..aab445cb197 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2012, 2018, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -113,19 +113,19 @@ struct row_index_t {
struct row_import {
row_import() UNIV_NOTHROW
:
- m_table(),
- m_version(),
- m_hostname(),
- m_table_name(),
- m_autoinc(),
+ m_table(NULL),
+ m_version(0),
+ m_hostname(NULL),
+ m_table_name(NULL),
+ m_autoinc(0),
m_page_size(0, 0, false),
- m_flags(),
- m_n_cols(),
- m_cols(),
- m_col_names(),
- m_n_indexes(),
- m_indexes(),
- m_missing(true) {}
+ m_flags(0),
+ m_n_cols(0),
+ m_cols(NULL),
+ m_col_names(NULL),
+ m_n_indexes(0),
+ m_indexes(NULL),
+ m_missing(true) { }
~row_import() UNIV_NOTHROW;
@@ -1227,17 +1227,63 @@ row_import::match_schema(
{
/* Do some simple checks. */
- if ((m_table->flags ^ m_flags) & ~DICT_TF_MASK_DATA_DIR) {
+ if (ulint mismatch = (m_table->flags ^ m_flags)
+ & ~DICT_TF_MASK_DATA_DIR) {
+ const char* msg;
+ if (mismatch & DICT_TF_MASK_ZIP_SSIZE) {
+ if ((m_table->flags & DICT_TF_MASK_ZIP_SSIZE)
+ && (m_flags & DICT_TF_MASK_ZIP_SSIZE)) {
+ switch (m_flags & DICT_TF_MASK_ZIP_SSIZE) {
+ case 0U << DICT_TF_POS_ZIP_SSIZE:
+ goto uncompressed;
+ case 1U << DICT_TF_POS_ZIP_SSIZE:
+ msg = "ROW_FORMAT=COMPRESSED"
+ " KEY_BLOCK_SIZE=1";
+ break;
+ case 2U << DICT_TF_POS_ZIP_SSIZE:
+ msg = "ROW_FORMAT=COMPRESSED"
+ " KEY_BLOCK_SIZE=2";
+ break;
+ case 3U << DICT_TF_POS_ZIP_SSIZE:
+ msg = "ROW_FORMAT=COMPRESSED"
+ " KEY_BLOCK_SIZE=4";
+ break;
+ case 4U << DICT_TF_POS_ZIP_SSIZE:
+ msg = "ROW_FORMAT=COMPRESSED"
+ " KEY_BLOCK_SIZE=8";
+ break;
+ case 5U << DICT_TF_POS_ZIP_SSIZE:
+ msg = "ROW_FORMAT=COMPRESSED"
+ " KEY_BLOCK_SIZE=16";
+ break;
+ default:
+ msg = "strange KEY_BLOCK_SIZE";
+ }
+ } else if (m_flags & DICT_TF_MASK_ZIP_SSIZE) {
+ msg = "ROW_FORMAT=COMPRESSED";
+ } else {
+ goto uncompressed;
+ }
+ } else {
+uncompressed:
+ msg = (m_flags & DICT_TF_MASK_ATOMIC_BLOBS)
+ ? "ROW_FORMAT=DYNAMIC"
+ : (m_flags & DICT_TF_MASK_COMPACT)
+ ? "ROW_FORMAT=COMPACT"
+ : "ROW_FORMAT=REDUNDANT";
+ }
+
ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH,
"Table flags don't match, server table has 0x%x"
- " and the meta-data file has 0x" ULINTPFx,
- m_table->flags, m_flags);
+ " and the meta-data file has 0x" ULINTPFx ";"
+ " .cfg file uses %s",
+ m_table->flags, m_flags, msg);
return(DB_ERROR);
} else if (m_table->n_cols != m_n_cols) {
ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH,
- "Number of columns don't match, table has %u"
- " columns but the tablespace meta-data file has "
+ "Number of columns don't match, table has %u "
+ "columns but the tablespace meta-data file has "
ULINTPF " columns",
m_table->n_cols, m_n_cols);
@@ -1686,7 +1732,6 @@ PageConverter::update_records(
while (!m_rec_iter.end()) {
rec_t* rec = m_rec_iter.current();
-
ibool deleted = rec_get_deleted_flag(rec, comp);
/* For the clustered index we have to adjust the BLOB
@@ -2359,8 +2404,6 @@ row_import_cfg_read_index_fields(
dict_field_t* field = index->m_fields;
- memset(field, 0x0, sizeof(*field) * n_fields);
-
for (ulint i = 0; i < n_fields; ++i, ++field) {
byte* ptr = row;
@@ -2378,6 +2421,8 @@ row_import_cfg_read_index_fields(
return(DB_IO_ERROR);
}
+ new (field) dict_field_t();
+
field->prefix_len = mach_read_from_4(ptr);
ptr += sizeof(ib_uint32_t);
@@ -3787,8 +3832,6 @@ row_import_for_mysql(
row_import cfg;
- memset(&cfg, 0x0, sizeof(cfg));
-
err = row_import_read_cfg(table, trx->mysql_thd, cfg);
/* Check if the table column definitions match the contents
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 37ae828d09d..c6ac98f1082 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -1660,7 +1660,8 @@ row_ins_check_foreign_constraint(
if (check_table == NULL
|| !check_table->is_readable()
- || check_index == NULL) {
+ || check_index == NULL
+ || check_table->space->is_being_truncated) {
if (!srv_read_only_mode && check_ref) {
FILE* ef = dict_foreign_err_file;
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 49ac2638ef8..a3c3d0eaaa6 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -72,6 +72,13 @@ Created 9/17/2000 Heikki Tuuri
#include <deque>
#include <vector>
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h"
+#include "wsrep.h"
+#include "log.h"
+#include "wsrep_mysqld.h"
+#endif
+
/** Provide optional 4.x backwards compatibility for 5.0 and above */
ibool row_rollback_on_timeout = FALSE;
@@ -1568,7 +1575,7 @@ error_exit:
memcpy(prebuilt->row_id, node->sys_buf, DATA_ROW_ID_LEN);
}
- dict_stats_update_if_needed(table);
+ dict_stats_update_if_needed(table, trx->mysql_thd);
trx->op_info = "";
if (blob_heap != NULL) {
@@ -1952,7 +1959,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt)
}
if (update_statistics) {
- dict_stats_update_if_needed(prebuilt->table);
+ dict_stats_update_if_needed(prebuilt->table, trx->mysql_thd);
} else {
/* Always update the table modification counter. */
prebuilt->table->stat_modified_counter++;
@@ -2195,7 +2202,7 @@ static dberr_t row_update_vers_insert(que_thr_t* thr, upd_node_t* node)
case DB_SUCCESS:
srv_stats.n_rows_inserted.inc(
static_cast<size_t>(trx->id));
- dict_stats_update_if_needed(table);
+ dict_stats_update_if_needed(table, trx->mysql_thd);
goto exit;
}
}
@@ -2288,7 +2295,8 @@ row_update_cascade_for_mysql(
}
if (stats) {
- dict_stats_update_if_needed(node->table);
+ dict_stats_update_if_needed(node->table,
+ trx->mysql_thd);
} else {
/* Always update the table
modification counter. */
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index 79ce3057cd7..e2bbb5a3d5e 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -1156,9 +1156,9 @@ row_purge_record_func(
/*==================*/
purge_node_t* node, /*!< in: row purge node */
trx_undo_rec_t* undo_rec, /*!< in: record to purge */
-#ifdef UNIV_DEBUG
+#if defined UNIV_DEBUG || defined WITH_WSREP
const que_thr_t*thr, /*!< in: query thread */
-#endif /* UNIV_DEBUG */
+#endif /* UNIV_DEBUG || WITH_WSREP */
bool updated_extern) /*!< in: whether external columns
were updated */
{
@@ -1179,7 +1179,9 @@ row_purge_record_func(
if (purged) {
if (node->table->stat_initialized
&& srv_stats_include_delete_marked) {
- dict_stats_update_if_needed(node->table);
+ dict_stats_update_if_needed(
+ node->table,
+ thr->graph->trx->mysql_thd);
}
MONITOR_INC(MONITOR_N_DEL_ROW_PURGE);
}
@@ -1214,13 +1216,13 @@ row_purge_record_func(
return(purged);
}
-#ifdef UNIV_DEBUG
+#if defined UNIV_DEBUG || defined WITH_WSREP
# define row_purge_record(node,undo_rec,thr,updated_extern) \
row_purge_record_func(node,undo_rec,thr,updated_extern)
-#else /* UNIV_DEBUG */
+#else /* UNIV_DEBUG || WITH_WSREP */
# define row_purge_record(node,undo_rec,thr,updated_extern) \
row_purge_record_func(node,undo_rec,updated_extern)
-#endif /* UNIV_DEBUG */
+#endif /* UNIV_DEBUG || WITH_WSREP */
/***********************************************************//**
Fetches an undo log record and does the purge for the recorded operation.
diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc
index abd037e4a49..65170a10f57 100644
--- a/storage/innobase/row/row0trunc.cc
+++ b/storage/innobase/row/row0trunc.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2013, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2013, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -1181,6 +1181,11 @@ row_truncate_complete(
{
bool is_file_per_table = dict_table_is_file_per_table(table);
+ /* Add the table back to FTS optimize background thread. */
+ if (table->fts) {
+ fts_optimize_add_table(table);
+ }
+
row_mysql_unlock_data_dictionary(trx);
DEBUG_SYNC_C("ib_trunc_table_trunc_completing");
@@ -1507,6 +1512,9 @@ row_truncate_update_system_tables(
/* Reset the Doc ID in cache to 0 */
if (has_internal_doc_id && table->fts->cache != NULL) {
+ DBUG_EXECUTE_IF("ib_trunc_sleep_before_fts_cache_clear",
+ os_thread_sleep(10000000););
+
table->fts->fts_status |= TABLE_DICT_LOCKED;
fts_update_next_doc_id(trx, table, NULL, 0);
fts_cache_clear(table->fts->cache);
@@ -1754,6 +1762,10 @@ row_truncate_table_for_mysql(
}
if (!table->is_temporary()) {
+ if (table->fts) {
+ fts_optimize_remove_table(table);
+ }
+
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
}
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index cbcb4eb8d1d..2067e957f3c 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.cc
@@ -273,8 +273,6 @@ row_undo_ins_remove_sec_low(
enum row_search_result search_result;
const bool modify_leaf = mode == BTR_MODIFY_LEAF;
- memset(&pcur, 0, sizeof(pcur));
-
row_mtr_start(&mtr, index, !modify_leaf);
if (modify_leaf) {
@@ -631,7 +629,8 @@ row_undo_ins(
already be holding dict_sys->mutex, which
would be acquired when updating statistics. */
if (!dict_locked) {
- dict_stats_update_if_needed(node->table);
+ dict_stats_update_if_needed(
+ node->table, node->trx->mysql_thd);
}
}
}
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index 64d771d7d94..90bce6c8be6 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -1351,7 +1351,8 @@ rollback_clust:
already be holding dict_sys->mutex, which
would be acquired when updating statistics. */
if (update_statistics && !dict_locked) {
- dict_stats_update_if_needed(node->table);
+ dict_stats_update_if_needed(
+ node->table, node->trx->mysql_thd);
} else {
node->table->stat_modified_counter++;
}
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc
index ab4814f3177..d5b0537c095 100644
--- a/storage/innobase/sync/sync0rw.cc
+++ b/storage/innobase/sync/sync0rw.cc
@@ -1042,86 +1042,52 @@ rw_lock_own(
return(false);
}
-/** For collecting the debug information for a thread's rw-lock */
-typedef std::vector<rw_lock_debug_t*> Infos;
-
-/** Get the thread debug info
-@param[in] infos The rw-lock mode owned by the threads
-@param[in] lock rw-lock to check
-@return the thread debug info or NULL if not found */
-void
-rw_lock_get_debug_info(const rw_lock_t* lock, Infos* infos)
-{
- rw_lock_debug_t* info = NULL;
-
- ut_ad(rw_lock_validate(lock));
-
- rw_lock_debug_mutex_enter();
-
- for (info = UT_LIST_GET_FIRST(lock->debug_list);
- info != NULL;
- info = UT_LIST_GET_NEXT(list, info)) {
-
- if (os_thread_eq(info->thread_id, os_thread_get_curr_id())) {
-
- infos->push_back(info);
- }
- }
-
- rw_lock_debug_mutex_exit();
-}
-
/** Checks if the thread has locked the rw-lock in the specified mode, with
the pass value == 0.
@param[in] lock rw-lock
@param[in] flags specify lock types with OR of the
rw_lock_flag_t values
@return true if locked */
-bool
-rw_lock_own_flagged(
- const rw_lock_t* lock,
- rw_lock_flags_t flags)
+bool rw_lock_own_flagged(const rw_lock_t* lock, rw_lock_flags_t flags)
{
- Infos infos;
-
- rw_lock_get_debug_info(lock, &infos);
-
- Infos::const_iterator end = infos.end();
-
- for (Infos::const_iterator it = infos.begin(); it != end; ++it) {
+ ut_ad(rw_lock_validate(lock));
- const rw_lock_debug_t* info = *it;
+ rw_lock_debug_mutex_enter();
- if (info->pass) {
+ for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(lock->debug_list);
+ info != NULL;
+ info = UT_LIST_GET_NEXT(list, info)) {
+ if (!os_thread_eq(info->thread_id, os_thread_get_curr_id())
+ || info->pass) {
continue;
}
- ut_ad(os_thread_eq(info->thread_id, os_thread_get_curr_id()));
-
switch (info->lock_type) {
case RW_LOCK_S:
-
- if (flags & RW_LOCK_FLAG_S) {
- return(true);
+ if (!(flags & RW_LOCK_FLAG_S)) {
+ continue;
}
break;
case RW_LOCK_X:
-
- if (flags & RW_LOCK_FLAG_X) {
- return(true);
+ if (!(flags & RW_LOCK_FLAG_X)) {
+ continue;
}
break;
case RW_LOCK_SX:
-
- if (flags & RW_LOCK_FLAG_SX) {
- return(true);
+ if (!(flags & RW_LOCK_FLAG_SX)) {
+ continue;
}
+ break;
}
+
+ rw_lock_debug_mutex_exit();
+ return true;
}
- return(false);
+ rw_lock_debug_mutex_exit();
+ return false;
}
/***************************************************************//**
@@ -1222,28 +1188,31 @@ rw_lock_t::locked_from() const
the same thread can call X lock recursively. */
std::ostringstream msg;
- Infos infos;
+ bool written = false;
- rw_lock_get_debug_info(this, &infos);
+ ut_ad(rw_lock_validate(this));
- ulint i = 0;
- Infos::const_iterator end = infos.end();
-
- for (Infos::const_iterator it = infos.begin(); it != end; ++it, ++i) {
-
- const rw_lock_debug_t* info = *it;
+ rw_lock_debug_mutex_enter();
- ut_ad(os_thread_eq(info->thread_id, os_thread_get_curr_id()));
+ for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(debug_list);
+ info != NULL;
+ info = UT_LIST_GET_NEXT(list, info)) {
+ if (!os_thread_eq(info->thread_id, os_thread_get_curr_id())) {
+ continue;
+ }
- if (i > 0) {
+ if (written) {
msg << ", ";
}
+ written = true;
+
msg << info->file_name << ":" << info->line;
}
- return(msg.str());
+ rw_lock_debug_mutex_exit();
+ return(msg.str());
}
/** Print the rw-lock information.
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index 81ad85dca7d..0e56af81ed4 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -545,9 +545,7 @@ trx_rseg_array_init()
*trx_sys.recovered_binlog_filename = '\0';
trx_sys.recovered_binlog_offset = 0;
#ifdef WITH_WSREP
- memset(&trx_sys.recovered_wsrep_xid, 0,
- sizeof trx_sys.recovered_wsrep_xid);
- trx_sys.recovered_wsrep_xid.formatID = -1;
+ trx_sys.recovered_wsrep_xid.null();
#endif
for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) {
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index c13ccdf53ed..5b3e4f04bd5 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -955,8 +955,7 @@ trx_start_low(
}
#ifdef WITH_WSREP
- memset(trx->xid, 0, sizeof(xid_t));
- trx->xid->formatID = -1;
+ trx->xid->null();
#endif /* WITH_WSREP */
/* The initial value for trx->no: TRX_ID_MAX is used in