Merge 10.2 into 10.3

This commit is contained in:
Marko Mäkelä 2018-05-07 15:50:38 +03:00
commit 1a4c355a1c
16 changed files with 115 additions and 85 deletions

View file

@ -0,0 +1,27 @@
CREATE TABLE t1 (a INT, b VARCHAR(10)) ENGINE=InnoDB
PARTITION BY RANGE(a)
(PARTITION pa VALUES LESS THAN (3),
PARTITION pb VALUES LESS THAN (5));
INSERT INTO t1 VALUES(2,'two'),(2,'two'),(4,'four');
connect ddl,localhost,root,,test;
SET DEBUG_SYNC = 'inplace_after_index_build SIGNAL go WAIT_FOR done';
ALTER TABLE t1 ADD UNIQUE KEY (a,b(3));
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR go';
BEGIN;
SELECT * FROM t1 FOR UPDATE;
a b
2 two
2 two
4 four
SET DEBUG_SYNC = 'now SIGNAL done';
connection ddl;
ERROR 23000: Duplicate entry '2-two' for key 'a'
connection default;
DELETE FROM t1;
disconnect ddl;
SET DEBUG_SYNC = 'RESET';
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;

View file

@ -0,0 +1,34 @@
--source include/have_innodb.inc
--source include/have_partition.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
CREATE TABLE t1 (a INT, b VARCHAR(10)) ENGINE=InnoDB
PARTITION BY RANGE(a)
(PARTITION pa VALUES LESS THAN (3),
PARTITION pb VALUES LESS THAN (5));
INSERT INTO t1 VALUES(2,'two'),(2,'two'),(4,'four');
connect ddl,localhost,root,,test;
SET DEBUG_SYNC = 'inplace_after_index_build SIGNAL go WAIT_FOR done';
send ALTER TABLE t1 ADD UNIQUE KEY (a,b(3));
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR go';
BEGIN;
SELECT * FROM t1 FOR UPDATE;
SET DEBUG_SYNC = 'now SIGNAL done';
connection ddl;
--error ER_DUP_ENTRY
reap;
connection default;
DELETE FROM t1;
disconnect ddl;
SET DEBUG_SYNC = 'RESET';
CHECK TABLE t1;
DROP TABLE t1;

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2016, MariaDB Corporation. 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
@ -232,7 +232,7 @@ dict_stats_process_entry_from_defrag_pool()
? dict_table_find_index_on_id(table, index_id)
: NULL;
if (!index || dict_index_is_corrupted(index)) {
if (!index || index->is_corrupted()) {
if (table) {
dict_table_close(table, TRUE, FALSE);
}

View file

@ -2481,10 +2481,10 @@ dict_load_indexes(
}
ut_ad(index);
ut_ad(!dict_index_is_online_ddl(index));
/* Check whether the index is corrupted */
if (dict_index_is_corrupted(index)) {
if (index->is_corrupted()) {
ib::error() << "Index " << index->name
<< " of table " << table->name
<< " is corrupted";
@ -3002,10 +3002,7 @@ err_exit:
table = NULL;
goto func_exit;
} else {
dict_index_t* clust_index;
clust_index = dict_table_get_first_index(table);
if (dict_index_is_corrupted(clust_index)) {
if (table->indexes.start->is_corrupted()) {
table->corrupted = true;
}
}
@ -3056,14 +3053,11 @@ err_exit:
if (!srv_force_recovery
|| !index
|| !dict_index_is_clust(index)) {
|| !index->is_primary()) {
dict_table_remove_from_cache(table);
table = NULL;
} else if (dict_index_is_corrupted(index)
} else if (index->is_corrupted()
&& table->is_readable()) {
/* It is possible we force to load a corrupted
clustered index if srv_load_corrupted is set.
Mark the table as corrupted in this case */

View file

@ -158,9 +158,8 @@ dict_stats_should_ignore_index(
/*===========================*/
const dict_index_t* index) /*!< in: index */
{
return((index->type & DICT_FTS)
|| dict_index_is_corrupted(index)
|| dict_index_is_spatial(index)
return((index->type & (DICT_FTS | DICT_SPATIAL))
|| index->is_corrupted()
|| index->to_be_dropped
|| !index->is_committed());
}
@ -2230,7 +2229,7 @@ dict_stats_update_persistent(
index = dict_table_get_first_index(table);
if (index == NULL
|| dict_index_is_corrupted(index)
|| index->is_corrupted()
|| (index->type | DICT_UNIQUE) != (DICT_CLUSTERED | DICT_UNIQUE)) {
/* Table definition is corrupt */

View file

@ -6526,7 +6526,7 @@ fts_check_corrupt_index(
if (index->id == aux_table->index_id) {
ut_ad(index->type & DICT_FTS);
dict_table_close(table, true, false);
return(dict_index_is_corrupted(index));
return index->is_corrupted();
}
}

View file

@ -9259,13 +9259,13 @@ ha_innobase::index_read(
dict_index_t* index = m_prebuilt->index;
if (index == NULL || dict_index_is_corrupted(index)) {
if (index == NULL || index->is_corrupted()) {
m_prebuilt->index_usable = FALSE;
DBUG_RETURN(HA_ERR_CRASHED);
}
if (!m_prebuilt->index_usable) {
DBUG_RETURN(dict_index_is_corrupted(index)
DBUG_RETURN(index->is_corrupted()
? HA_ERR_INDEX_CORRUPT
: HA_ERR_TABLE_DEF_CHANGED);
}
@ -9523,14 +9523,14 @@ ha_innobase::change_active_index(
m_prebuilt->trx, m_prebuilt->index);
if (!m_prebuilt->index_usable) {
if (dict_index_is_corrupted(m_prebuilt->index)) {
if (m_prebuilt->index->is_corrupted()) {
char table_name[MAX_FULL_NAME_LEN + 1];
innobase_format_name(
table_name, sizeof table_name,
m_prebuilt->index->table->name.m_name);
if (dict_index_is_clust(m_prebuilt->index)) {
if (m_prebuilt->index->is_primary()) {
ut_ad(m_prebuilt->index->table->corrupted);
push_warning_printf(
m_user_thd, Sql_condition::WARN_LEVEL_WARN,
@ -13380,7 +13380,7 @@ ha_innobase::records_in_range(
n_rows = HA_POS_ERROR;
goto func_exit;
}
if (dict_index_is_corrupted(index)) {
if (index->is_corrupted()) {
n_rows = HA_ERR_INDEX_CORRUPT;
goto func_exit;
}
@ -14220,7 +14220,7 @@ ha_innobase::defragment_table(
for (index = dict_table_get_first_index(table); index;
index = dict_table_get_next_index(index)) {
if (dict_index_is_corrupted(index)) {
if (index->is_corrupted()) {
continue;
}
@ -14417,7 +14417,7 @@ ha_innobase::check(
clustered index, we will do so here */
index = dict_table_get_first_index(m_prebuilt->table);
if (!dict_index_is_corrupted(index)) {
if (!index->is_corrupted()) {
dict_set_corrupted(
index, m_prebuilt->trx, "CHECK TABLE");
}
@ -14455,7 +14455,7 @@ ha_innobase::check(
}
if (!(check_opt->flags & T_QUICK)
&& !dict_index_is_corrupted(index)) {
&& !index->is_corrupted()) {
/* Enlarge the fatal lock wait timeout during
CHECK TABLE. */
my_atomic_addlong(
@ -14507,7 +14507,7 @@ ha_innobase::check(
DBUG_EXECUTE_IF(
"dict_set_index_corrupted",
if (!dict_index_is_clust(index)) {
if (!index->is_primary()) {
m_prebuilt->index_usable = FALSE;
// row_mysql_lock_data_dictionary(m_prebuilt->trx);
dict_set_corrupted(index, m_prebuilt->trx, "dict_set_index_corrupted");
@ -14515,7 +14515,7 @@ ha_innobase::check(
});
if (UNIV_UNLIKELY(!m_prebuilt->index_usable)) {
if (dict_index_is_corrupted(m_prebuilt->index)) {
if (index->is_corrupted()) {
push_warning_printf(
m_user_thd,
Sql_condition::WARN_LEVEL_WARN,
@ -14555,7 +14555,7 @@ ha_innobase::check(
DBUG_EXECUTE_IF(
"dict_set_index_corrupted",
if (!dict_index_is_clust(index)) {
if (!index->is_primary()) {
ret = DB_CORRUPTION;
});

View file

@ -5232,8 +5232,7 @@ new_clustered_failed:
= dict_table_get_first_index(user_table);
index != NULL;
index = dict_table_get_next_index(index)) {
if (!index->to_be_dropped
&& dict_index_is_corrupted(index)) {
if (!index->to_be_dropped && index->is_corrupted()) {
my_error(ER_CHECK_NO_SUCH_TABLE, MYF(0));
goto error_handled;
}
@ -5243,8 +5242,7 @@ new_clustered_failed:
= dict_table_get_first_index(user_table);
index != NULL;
index = dict_table_get_next_index(index)) {
if (!index->to_be_dropped
&& dict_index_is_corrupted(index)) {
if (!index->to_be_dropped && index->is_corrupted()) {
my_error(ER_CHECK_NO_SUCH_TABLE, MYF(0));
goto error_handled;
}
@ -6322,8 +6320,7 @@ ha_innobase::prepare_inplace_alter_table(
if (indexed_table->corrupted
|| dict_table_get_first_index(indexed_table) == NULL
|| dict_index_is_corrupted(
dict_table_get_first_index(indexed_table))) {
|| dict_table_get_first_index(indexed_table)->is_corrupted()) {
/* The clustered index is corrupted. */
my_error(ER_CHECK_NO_SUCH_TABLE, MYF(0));
DBUG_RETURN(true);
@ -6611,7 +6608,7 @@ found_fk:
" with name %s", key->name);
} else {
ut_ad(!index->to_be_dropped);
if (!dict_index_is_clust(index)) {
if (!index->is_primary()) {
drop_index[n_drop_index++] = index;
} else {
drop_primary = index;
@ -6712,7 +6709,7 @@ check_if_can_drop_indexes:
for (dict_index_t* index = dict_table_get_first_index(indexed_table);
index != NULL; index = dict_table_get_next_index(index)) {
if (!index->to_be_dropped && dict_index_is_corrupted(index)) {
if (!index->to_be_dropped && index->is_corrupted()) {
my_error(ER_INDEX_CORRUPT, MYF(0), index->name());
goto err_exit;
}
@ -8440,7 +8437,7 @@ commit_try_rebuild(
DBUG_ASSERT(dict_index_get_online_status(index)
== ONLINE_INDEX_COMPLETE);
DBUG_ASSERT(index->is_committed());
if (dict_index_is_corrupted(index)) {
if (index->is_corrupted()) {
my_error(ER_INDEX_CORRUPT, MYF(0), index->name());
DBUG_RETURN(true);
}
@ -8689,7 +8686,7 @@ commit_try_norebuild(
DBUG_ASSERT(dict_index_get_online_status(index)
== ONLINE_INDEX_COMPLETE);
DBUG_ASSERT(!index->is_committed());
if (dict_index_is_corrupted(index)) {
if (index->is_corrupted()) {
/* Report a duplicate key
error for the index that was
flagged corrupted, most likely

View file

@ -683,7 +683,7 @@ dict_table_get_next_index(
/* Skip corrupted index */
#define dict_table_skip_corrupt_index(index) \
while (index && dict_index_is_corrupted(index)) { \
while (index && index->is_corrupted()) { \
index = dict_table_get_next_index(index); \
}
@ -1769,16 +1769,6 @@ dict_table_is_corrupted(
const dict_table_t* table) /*!< in: table */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/**********************************************************************//**
Check whether the index is corrupted.
@return nonzero for corrupted index, zero for valid indexes */
UNIV_INLINE
ulint
dict_index_is_corrupted(
/*====================*/
const dict_index_t* index) /*!< in: index */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/**********************************************************************//**
Flags an index and table corrupted both in the data dictionary cache
and in the system table SYS_INDEXES. */

View file

@ -1390,21 +1390,6 @@ dict_table_is_corrupted(
return(table->corrupted);
}
/********************************************************************//**
Check whether the index is corrupted.
@return nonzero for corrupted index, zero for valid indexes */
UNIV_INLINE
ulint
dict_index_is_corrupted(
/*====================*/
const dict_index_t* index) /*!< in: index */
{
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
return((index->type & DICT_CORRUPT)
|| (index->table && index->table->corrupted));
}
/********************************************************************//**
Check if the tablespace for the table has been discarded.
@return true if the tablespace has been discarded. */

View file

@ -1045,6 +1045,9 @@ struct dict_index_t{
return DICT_CLUSTERED == (type & (DICT_CLUSTERED | DICT_IBUF));
}
/** @return whether the index is corrupted */
inline bool is_corrupted() const;
/** Determine how many fields of a given prefix can be set NULL.
@param[in] n_prefix number of fields in the prefix
@return number of fields 0..n_prefix-1 that can be set NULL */
@ -1934,6 +1937,13 @@ inline bool dict_index_t::is_instant() const
return(n_core_fields != n_fields);
}
inline bool dict_index_t::is_corrupted() const
{
return UNIV_UNLIKELY(online_status >= ONLINE_INDEX_ABORTED
|| (type & DICT_CORRUPT)
|| (table && table->corrupted));
}
/*******************************************************************//**
Initialise the table lock list. */
void

View file

@ -3774,8 +3774,7 @@ row_ins(
node->index = NULL; node->entry = NULL; break;);
/* Skip corrupted secondary index and its entry */
while (node->index && dict_index_is_corrupted(node->index)) {
while (node->index && node->index->is_corrupted()) {
node->index = dict_table_get_next_index(node->index);
node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
}

View file

@ -328,7 +328,7 @@ row_log_online_op(
ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_S)
|| rw_lock_own(dict_index_get_lock(index), RW_LOCK_X));
if (dict_index_is_corrupted(index)) {
if (index->is_corrupted()) {
return;
}
@ -648,8 +648,8 @@ row_log_table_delete(
&index->lock,
RW_LOCK_FLAG_S | RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX));
if (dict_index_is_corrupted(index)
|| !dict_index_is_online_ddl(index)
if (index->online_status != ONLINE_INDEX_CREATION
|| (index->type & DICT_CORRUPT) || index->table->corrupted
|| index->online_log->error != DB_SUCCESS) {
return;
}
@ -1016,8 +1016,8 @@ row_log_table_low(
ut_ad(!old_pk || !insert);
ut_ad(!old_pk || old_pk->n_v_fields == 0);
if (dict_index_is_corrupted(index)
|| !dict_index_is_online_ddl(index)
if (index->online_status != ONLINE_INDEX_CREATION
|| (index->type & DICT_CORRUPT) || index->table->corrupted
|| index->online_log->error != DB_SUCCESS) {
return;
}
@ -2826,7 +2826,7 @@ next_block:
goto interrupted;
}
if (dict_index_is_corrupted(index)) {
if (index->is_corrupted()) {
error = DB_INDEX_CORRUPT;
goto func_exit;
}
@ -3330,7 +3330,7 @@ row_log_apply_op_low(
ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_X)
== has_index_lock);
ut_ad(!dict_index_is_corrupted(index));
ut_ad(!index->is_corrupted());
ut_ad(trx_id != 0 || op == ROW_OP_DELETE);
DBUG_LOG("ib_create_index",
@ -3574,7 +3574,7 @@ row_log_apply_op(
ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_X)
== has_index_lock);
if (dict_index_is_corrupted(index)) {
if (index->is_corrupted()) {
*error = DB_INDEX_CORRUPT;
return(NULL);
}
@ -3711,7 +3711,7 @@ next_block:
goto func_exit;
}
if (dict_index_is_corrupted(index)) {
if (index->is_corrupted()) {
error = DB_INDEX_CORRUPT;
goto func_exit;
}

View file

@ -4483,13 +4483,13 @@ row_merge_is_index_usable(
const trx_t* trx, /*!< in: transaction */
const dict_index_t* index) /*!< in: index to check */
{
if (!dict_index_is_clust(index)
if (!index->is_primary()
&& dict_index_is_online_ddl(index)) {
/* Indexes that are being created are not useable. */
return(false);
}
return(!dict_index_is_corrupted(index)
return(!index->is_corrupted()
&& (dict_table_is_temporary(index->table)
|| index->trx_id == 0
|| !trx->read_view.is_open()

View file

@ -972,8 +972,7 @@ try_again:
clust_index = dict_table_get_first_index(node->table);
if (clust_index == NULL
|| dict_index_is_corrupted(clust_index)) {
if (!clust_index || clust_index->is_corrupted()) {
/* The table was corrupt in the data dictionary.
dict_set_corrupted() works on an index, and
we do not have an index to call it with. */

View file

@ -4219,18 +4219,14 @@ row_search_mvcc(
ut_ad(!sync_check_iterate(sync_check()));
if (dict_table_is_discarded(prebuilt->table)) {
DBUG_RETURN(DB_TABLESPACE_DELETED);
} else if (!prebuilt->table->is_readable()) {
DBUG_RETURN(prebuilt->table->space
? DB_DECRYPTION_FAILED
: DB_TABLESPACE_NOT_FOUND);
} else if (!prebuilt->index_usable) {
DBUG_RETURN(DB_MISSING_HISTORY);
} else if (dict_index_is_corrupted(prebuilt->index)) {
} else if (prebuilt->index->is_corrupted()) {
DBUG_RETURN(DB_CORRUPTION);
}