Commit 5b3c1007 authored by Sergei Golubchik's avatar Sergei Golubchik

Merge branch 'merge/merge-innodb-5.6' into 10.0

parents 16239951 e9eaaa4b
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. Copyright (c) 2012, Facebook Inc.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
...@@ -2101,7 +2101,7 @@ the tuple. It is assumed that mtr contains an x-latch on the tree. ...@@ -2101,7 +2101,7 @@ the tuple. It is assumed that mtr contains an x-latch on the tree.
NOTE that the operation of this function must always succeed, NOTE that the operation of this function must always succeed,
we cannot reverse it: therefore enough free disk space must be we cannot reverse it: therefore enough free disk space must be
guaranteed to be available before this function is called. guaranteed to be available before this function is called.
@return inserted record */ @return inserted record or NULL if run out of space */
UNIV_INTERN UNIV_INTERN
rec_t* rec_t*
btr_root_raise_and_insert( btr_root_raise_and_insert(
...@@ -2162,6 +2162,11 @@ btr_root_raise_and_insert( ...@@ -2162,6 +2162,11 @@ btr_root_raise_and_insert(
level = btr_page_get_level(root, mtr); level = btr_page_get_level(root, mtr);
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr); new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr);
if (new_block == NULL && os_has_said_disk_full) {
return(NULL);
}
new_page = buf_block_get_frame(new_block); new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block); new_page_zip = buf_block_get_page_zip(new_block);
ut_a(!new_page_zip == !root_page_zip); ut_a(!new_page_zip == !root_page_zip);
...@@ -2938,7 +2943,7 @@ function must always succeed, we cannot reverse it: therefore enough ...@@ -2938,7 +2943,7 @@ function must always succeed, we cannot reverse it: therefore enough
free disk space (2 pages) must be guaranteed to be available before free disk space (2 pages) must be guaranteed to be available before
this function is called. this function is called.
@return inserted record */ @return inserted record or NULL if run out of space */
UNIV_INTERN UNIV_INTERN
rec_t* rec_t*
btr_page_split_and_insert( btr_page_split_and_insert(
...@@ -3052,9 +3057,18 @@ func_start: ...@@ -3052,9 +3057,18 @@ func_start:
} }
} }
DBUG_EXECUTE_IF("disk_is_full",
os_has_said_disk_full = true;
return(NULL););
/* 2. Allocate a new page to the index */ /* 2. Allocate a new page to the index */
new_block = btr_page_alloc(cursor->index, hint_page_no, direction, new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
btr_page_get_level(page, mtr), mtr, mtr); btr_page_get_level(page, mtr), mtr, mtr);
if (new_block == NULL && os_has_said_disk_full) {
return(NULL);
}
new_page = buf_block_get_frame(new_block); new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block); new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, cursor->index, btr_page_create(new_block, new_page_zip, cursor->index,
......
...@@ -1605,6 +1605,10 @@ btr_cur_pessimistic_insert( ...@@ -1605,6 +1605,10 @@ btr_cur_pessimistic_insert(
flags, cursor, offsets, heap, entry, n_ext, mtr); flags, cursor, offsets, heap, entry, n_ext, mtr);
} }
if (*rec == NULL && os_has_said_disk_full) {
return(DB_OUT_OF_FILE_SPACE);
}
ut_ad(page_rec_get_next(btr_cur_get_rec(cursor)) == *rec); ut_ad(page_rec_get_next(btr_cur_get_rec(cursor)) == *rec);
if (!(flags & BTR_NO_LOCKING_FLAG)) { if (!(flags & BTR_NO_LOCKING_FLAG)) {
......
...@@ -1628,10 +1628,13 @@ dict_table_rename_in_cache( ...@@ -1628,10 +1628,13 @@ dict_table_rename_in_cache(
to preserve the original table name to preserve the original table name
in constraints which reference it */ in constraints which reference it */
{ {
dberr_t err;
dict_foreign_t* foreign; dict_foreign_t* foreign;
dict_index_t* index; dict_index_t* index;
ulint fold; ulint fold;
char old_name[MAX_FULL_NAME_LEN + 1]; char old_name[MAX_FULL_NAME_LEN + 1];
os_file_type_t ftype;
ibool exists;
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
...@@ -1669,8 +1672,6 @@ dict_table_rename_in_cache( ...@@ -1669,8 +1672,6 @@ dict_table_rename_in_cache(
.ibd file and rebuild the .isl file if needed. */ .ibd file and rebuild the .isl file if needed. */
if (dict_table_is_discarded(table)) { if (dict_table_is_discarded(table)) {
os_file_type_t type;
ibool exists;
char* filepath; char* filepath;
ut_ad(table->space != TRX_SYS_SPACE); ut_ad(table->space != TRX_SYS_SPACE);
...@@ -1689,7 +1690,7 @@ dict_table_rename_in_cache( ...@@ -1689,7 +1690,7 @@ dict_table_rename_in_cache(
fil_delete_tablespace(table->space, BUF_REMOVE_ALL_NO_WRITE); fil_delete_tablespace(table->space, BUF_REMOVE_ALL_NO_WRITE);
/* Delete any temp file hanging around. */ /* Delete any temp file hanging around. */
if (os_file_status(filepath, &exists, &type) if (os_file_status(filepath, &exists, &ftype)
&& exists && exists
&& !os_file_delete_if_exists(innodb_file_temp_key, && !os_file_delete_if_exists(innodb_file_temp_key,
filepath)) { filepath)) {
...@@ -1701,8 +1702,6 @@ dict_table_rename_in_cache( ...@@ -1701,8 +1702,6 @@ dict_table_rename_in_cache(
mem_free(filepath); mem_free(filepath);
} else if (table->space != TRX_SYS_SPACE) { } else if (table->space != TRX_SYS_SPACE) {
char* new_path = NULL;
if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) { if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fputs(" InnoDB: Error: trying to rename a" fputs(" InnoDB: Error: trying to rename a"
...@@ -1716,34 +1715,43 @@ dict_table_rename_in_cache( ...@@ -1716,34 +1715,43 @@ dict_table_rename_in_cache(
} }
return(DB_ERROR); return(DB_ERROR);
}
} else if (DICT_TF_HAS_DATA_DIR(table->flags)) { char* new_path = NULL;
char* old_path; char* old_path = fil_space_get_first_path(table->space);
old_path = fil_space_get_first_path(table->space);
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
new_path = os_file_make_new_pathname( new_path = os_file_make_new_pathname(
old_path, new_name); old_path, new_name);
mem_free(old_path); err = fil_create_link_file(new_name, new_path);
dberr_t err = fil_create_link_file(
new_name, new_path);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
mem_free(new_path); mem_free(new_path);
mem_free(old_path);
return(DB_TABLESPACE_EXISTS); return(DB_TABLESPACE_EXISTS);
} }
} else {
new_path = fil_make_ibd_name(new_name, false);
}
/* New filepath must not exist. */
err = fil_rename_tablespace_check(
table->space, old_path, new_path, false);
if (err != DB_SUCCESS) {
mem_free(old_path);
mem_free(new_path);
return(err);
} }
ibool success = fil_rename_tablespace( ibool success = fil_rename_tablespace(
old_name, table->space, new_name, new_path); old_name, table->space, new_name, new_path);
mem_free(old_path);
mem_free(new_path);
/* If the tablespace is remote, a new .isl file was created /* If the tablespace is remote, a new .isl file was created
If success, delete the old one. If not, delete the new one. */ If success, delete the old one. If not, delete the new one. */
if (new_path) { if (DICT_TF_HAS_DATA_DIR(table->flags)) {
mem_free(new_path);
fil_delete_link_file(success ? old_name : new_name); fil_delete_link_file(success ? old_name : new_name);
} }
......
...@@ -2821,6 +2821,48 @@ fil_make_isl_name( ...@@ -2821,6 +2821,48 @@ fil_make_isl_name(
return(filename); return(filename);
} }
/** Test if a tablespace file can be renamed to a new filepath by checking
if that the old filepath exists and the new filepath does not exist.
@param[in] space_id tablespace id
@param[in] old_path old filepath
@param[in] new_path new filepath
@param[in] is_discarded whether the tablespace is discarded
@return innodb error code */
dberr_t
fil_rename_tablespace_check(
ulint space_id,
const char* old_path,
const char* new_path,
bool is_discarded)
{
ulint exists = false;
os_file_type_t ftype;
if (!is_discarded
&& os_file_status(old_path, &exists, &ftype)
&& !exists) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Cannot rename '%s' to '%s' for space ID %lu"
" because the source file does not exist.",
old_path, new_path, space_id);
return(DB_TABLESPACE_NOT_FOUND);
}
exists = false;
if (!os_file_status(new_path, &exists, &ftype) || exists) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Cannot rename '%s' to '%s' for space ID %lu"
" because the target file exists."
" Remove the target file and try again.",
old_path, new_path, space_id);
return(DB_TABLESPACE_EXISTS);
}
return(DB_SUCCESS);
}
/*******************************************************************//** /*******************************************************************//**
Renames a single-table tablespace. The tablespace must be cached in the Renames a single-table tablespace. The tablespace must be cached in the
tablespace memory cache. tablespace memory cache.
...@@ -6400,29 +6442,108 @@ fil_get_space_names( ...@@ -6400,29 +6442,108 @@ fil_get_space_names(
return(err); return(err);
} }
/****************************************************************//** /** Generate redo log for swapping two .ibd files
Generate redo logs for swapping two .ibd files */ @param[in] old_table old table
@param[in] new_table new table
@param[in] tmp_name temporary table name
@param[in,out] mtr mini-transaction
@return innodb error code */
UNIV_INTERN UNIV_INTERN
void dberr_t
fil_mtr_rename_log( fil_mtr_rename_log(
/*===============*/ const dict_table_t* old_table,
ulint old_space_id, /*!< in: tablespace id of the old const dict_table_t* new_table,
table. */ const char* tmp_name,
const char* old_name, /*!< in: old table name */ mtr_t* mtr)
ulint new_space_id, /*!< in: tablespace id of the new
table */
const char* new_name, /*!< in: new table name */
const char* tmp_name, /*!< in: temp table name used while
swapping */
mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
if (old_space_id != TRX_SYS_SPACE) { dberr_t err = DB_SUCCESS;
fil_op_write_log(MLOG_FILE_RENAME, old_space_id, char* old_path;
0, 0, old_name, tmp_name, mtr);
/* If neither table is file-per-table,
there will be no renaming of files. */
if (old_table->space == TRX_SYS_SPACE
&& new_table->space == TRX_SYS_SPACE) {
return(DB_SUCCESS);
}
if (DICT_TF_HAS_DATA_DIR(old_table->flags)) {
old_path = os_file_make_remote_pathname(
old_table->data_dir_path, old_table->name, "ibd");
} else {
old_path = fil_make_ibd_name(old_table->name, false);
}
if (old_path == NULL) {
return(DB_OUT_OF_MEMORY);
}
if (old_table->space != TRX_SYS_SPACE) {
char* tmp_path;
if (DICT_TF_HAS_DATA_DIR(old_table->flags)) {
tmp_path = os_file_make_remote_pathname(
old_table->data_dir_path, tmp_name, "ibd");
}
else {
tmp_path = fil_make_ibd_name(tmp_name, false);
}
if (tmp_path == NULL) {
mem_free(old_path);
return(DB_OUT_OF_MEMORY);
}
/* Temp filepath must not exist. */
err = fil_rename_tablespace_check(
old_table->space, old_path, tmp_path,
dict_table_is_discarded(old_table));
mem_free(tmp_path);
if (err != DB_SUCCESS) {
mem_free(old_path);
return(err);
}
fil_op_write_log(MLOG_FILE_RENAME, old_table->space,
0, 0, old_table->name, tmp_name, mtr);
} }
if (new_space_id != TRX_SYS_SPACE) { if (new_table->space != TRX_SYS_SPACE) {
fil_op_write_log(MLOG_FILE_RENAME, new_space_id,
0, 0, new_name, old_name, mtr); /* Destination filepath must not exist unless this ALTER
TABLE starts and ends with a file_per-table tablespace. */
if (old_table->space == TRX_SYS_SPACE) {
char* new_path = NULL;
if (DICT_TF_HAS_DATA_DIR(new_table->flags)) {
new_path = os_file_make_remote_pathname(
new_table->data_dir_path,
new_table->name, "ibd");
}
else {
new_path = fil_make_ibd_name(
new_table->name, false);
}
if (new_path == NULL) {
mem_free(old_path);
return(DB_OUT_OF_MEMORY);
}
err = fil_rename_tablespace_check(
new_table->space, new_path, old_path,
dict_table_is_discarded(new_table));
mem_free(new_path);
if (err != DB_SUCCESS) {
mem_free(old_path);
return(err);
}
}
fil_op_write_log(MLOG_FILE_RENAME, new_table->space,
0, 0, new_table->name, old_table->name, mtr);
} }
mem_free(old_path);
return(err);
} }
...@@ -952,10 +952,20 @@ fsp_try_extend_data_file( ...@@ -952,10 +952,20 @@ fsp_try_extend_data_file(
} }
} else { } else {
/* We extend single-table tablespaces first one extent /* We extend single-table tablespaces first one extent
at a time, but for bigger tablespaces more. It is not at a time, but 4 at a time for bigger tablespaces. It is
enough to extend always by one extent, because some not enough to extend always by one extent, because we need
extents are frag page extents. */ to add at least one extent to FSP_FREE.
A single extent descriptor page will track many extents.
And the extent that uses its extent descriptor page is
put onto the FSP_FREE_FRAG list. Extents that do not
use their extent descriptor page are added to FSP_FREE.
The physical page size is used to determine how many
extents are tracked on one extent descriptor page. */
ulint extent_size; /*!< one megabyte, in pages */ ulint extent_size; /*!< one megabyte, in pages */
ulint threshold; /*!< The size of the tablespace
(in number of pages) where we
start allocating more than one
extent at a time. */
if (!zip_size) { if (!zip_size) {
extent_size = FSP_EXTENT_SIZE; extent_size = FSP_EXTENT_SIZE;
...@@ -964,6 +974,14 @@ fsp_try_extend_data_file( ...@@ -964,6 +974,14 @@ fsp_try_extend_data_file(
* UNIV_PAGE_SIZE / zip_size; * UNIV_PAGE_SIZE / zip_size;
} }
/* Threshold is set at 32mb except when the page
size is small enough that it must be done sooner.
For page size less than 4k, we may reach the
extent contains extent descriptor page before
32 mb. */
threshold = ut_min((32 * extent_size),
(zip_size ? zip_size : UNIV_PAGE_SIZE));
if (size < extent_size) { if (size < extent_size) {
/* Let us first extend the file to extent_size */ /* Let us first extend the file to extent_size */
success = fsp_try_extend_data_file_with_pages( success = fsp_try_extend_data_file_with_pages(
...@@ -980,7 +998,7 @@ fsp_try_extend_data_file( ...@@ -980,7 +998,7 @@ fsp_try_extend_data_file(
size = extent_size; size = extent_size;
} }
if (size < 32 * extent_size) { if (size < threshold) {
size_increase = extent_size; size_increase = extent_size;
} else { } else {
/* Below in fsp_fill_free_list() we assume /* Below in fsp_fill_free_list() we assume
......
...@@ -162,10 +162,13 @@ my_error_innodb( ...@@ -162,10 +162,13 @@ my_error_innodb(
/* TODO: report the row, as we do for DB_DUPLICATE_KEY */ /* TODO: report the row, as we do for DB_DUPLICATE_KEY */
my_error(ER_INVALID_USE_OF_NULL, MYF(0)); my_error(ER_INVALID_USE_OF_NULL, MYF(0));
break; break;
case DB_TABLESPACE_EXISTS:
my_error(ER_TABLESPACE_EXISTS, MYF(0), table);
break;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
case DB_SUCCESS: case DB_SUCCESS:
case DB_DUPLICATE_KEY: case DB_DUPLICATE_KEY:
case DB_TABLESPACE_EXISTS:
case DB_ONLINE_LOG_TOO_BIG: case DB_ONLINE_LOG_TOO_BIG:
/* These codes should not be passed here. */ /* These codes should not be passed here. */
ut_error; ut_error;
...@@ -5141,6 +5144,61 @@ commit_cache_rebuild( ...@@ -5141,6 +5144,61 @@ commit_cache_rebuild(
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/** Store the column number of the columns in a list belonging
to indexes which are not being dropped.
@param[in] ctx In-place ALTER TABLE context
@param[out] drop_col_list list which will be set, containing columns
which is part of index being dropped */
static
void
get_col_list_to_be_dropped(
ha_innobase_inplace_ctx* ctx,
std::set<ulint>& drop_col_list)
{
for (ulint index_count = 0; index_count < ctx->num_to_drop_index;
index_count++) {
dict_index_t* index = ctx->drop_index[index_count];
for (ulint col = 0; col < index->n_user_defined_cols; col++) {
ulint col_no = dict_index_get_nth_col_no(index, col);
drop_col_list.insert(col_no);
}
}
}
/** For each column, which is part of an index which is not going to be
dropped, it checks if the column number of the column is same as col_no
argument passed.
@param[in] table table object
@param[in] col_no column number of the column which is to be checked
@retval true column exists
@retval false column does not exist. */
static
bool
check_col_exists_in_indexes(
const dict_table_t* table,
ulint col_no)
{
for (dict_index_t* index = dict_table_get_first_index(table); index;
index = dict_table_get_next_index(index)) {
if (index->to_be_dropped) {
continue;
}
for (ulint col = 0; col < index->n_user_defined_cols; col++) {
ulint index_col_no = dict_index_get_nth_col_no(
index, col);
if (col_no == index_col_no) {
return(true);
}
}
}
return(false);
}
/** Commit the changes made during prepare_inplace_alter_table() /** Commit the changes made during prepare_inplace_alter_table()
and inplace_alter_table() inside the data dictionary tables, and inplace_alter_table() inside the data dictionary tables,
when not rebuilding the table. when not rebuilding the table.
...@@ -5276,6 +5334,20 @@ commit_cache_norebuild( ...@@ -5276,6 +5334,20 @@ commit_cache_norebuild(
DBUG_ASSERT(!ctx->need_rebuild()); DBUG_ASSERT(!ctx->need_rebuild());
std::set<ulint> drop_list;
std::set<ulint>::const_iterator col_it;
/* Check if the column, part of an index to be dropped is part of any
other index which is not being dropped. If it so, then set the ord_part
of the column to 0. */
get_col_list_to_be_dropped(ctx, drop_list);
for(col_it = drop_list.begin(); col_it != drop_list.end(); ++col_it) {
if (!check_col_exists_in_indexes(ctx->new_table, *col_it)) {
ctx->new_table->cols[*col_it].ord_part = 0;
}
}
for (ulint i = 0; i < ctx->num_to_add_index; i++) { for (ulint i = 0; i < ctx->num_to_add_index; i++) {
dict_index_t* index = ctx->add_index[i]; dict_index_t* index = ctx->add_index[i];
DBUG_ASSERT(dict_index_get_online_status(index) DBUG_ASSERT(dict_index_get_online_status(index)
...@@ -5476,6 +5548,7 @@ ha_innobase::commit_inplace_alter_table( ...@@ -5476,6 +5548,7 @@ ha_innobase::commit_inplace_alter_table(
Alter_inplace_info* ha_alter_info, Alter_inplace_info* ha_alter_info,
bool commit) bool commit)
{ {
dberr_t error;
ha_innobase_inplace_ctx* ctx0 ha_innobase_inplace_ctx* ctx0
= static_cast<ha_innobase_inplace_ctx*> = static_cast<ha_innobase_inplace_ctx*>
(ha_alter_info->handler_ctx); (ha_alter_info->handler_ctx);
...@@ -5557,7 +5630,7 @@ ha_innobase::commit_inplace_alter_table( ...@@ -5557,7 +5630,7 @@ ha_innobase::commit_inplace_alter_table(
transactions collected during crash recovery could be transactions collected during crash recovery could be
holding InnoDB locks only, not MySQL locks. */ holding InnoDB locks only, not MySQL locks. */
dberr_t error = row_merge_lock_table( error = row_merge_lock_table(
prebuilt->trx, ctx->old_table, LOCK_X); prebuilt->trx, ctx->old_table, LOCK_X);
if (error != DB_SUCCESS) { if (error != DB_SUCCESS) {
...@@ -5692,14 +5765,20 @@ ha_innobase::commit_inplace_alter_table( ...@@ -5692,14 +5765,20 @@ ha_innobase::commit_inplace_alter_table(
= static_cast<ha_innobase_inplace_ctx*>(*pctx); = static_cast<ha_innobase_inplace_ctx*>(*pctx);
DBUG_ASSERT(ctx->need_rebuild()); DBUG_ASSERT(ctx->need_rebuild());
/* Generate the redo log for the file /* Check for any possible problems for any
operations that will be performed in file operations that will be performed in
commit_cache_rebuild(). */ commit_cache_rebuild(), and if none, generate
fil_mtr_rename_log(ctx->old_table->space, the redo log for these operations. */
ctx->old_table->name, error = fil_mtr_rename_log(ctx->old_table,
ctx->new_table->space, ctx->new_table,
ctx->new_table->name, ctx->tmp_name, &mtr);
ctx->tmp_name, &mtr); if (error != DB_SUCCESS) {
/* Out of memory or a problem will occur
when renaming files. */
fail = true;
my_error_innodb(error, ctx->old_table->name,
ctx->old_table->flags);
}
DBUG_INJECT_CRASH("ib_commit_inplace_crash", DBUG_INJECT_CRASH("ib_commit_inplace_crash",
crash_inject_count++); crash_inject_count++);
} }
...@@ -5712,18 +5791,25 @@ ha_innobase::commit_inplace_alter_table( ...@@ -5712,18 +5791,25 @@ ha_innobase::commit_inplace_alter_table(
DBUG_EXECUTE_IF("innodb_alter_commit_crash_before_commit", DBUG_EXECUTE_IF("innodb_alter_commit_crash_before_commit",
log_buffer_flush_to_disk(); log_buffer_flush_to_disk();
DBUG_SUICIDE();); DBUG_SUICIDE(););
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
ut_ad(!trx->fts_trx); ut_ad(!trx->fts_trx);
ut_ad(trx->insert_undo || trx->update_undo);
/* The following call commits the if (fail) {
mini-transaction, making the data dictionary mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
transaction committed at mtr.end_lsn. The mtr_commit(&mtr);
transaction becomes 'durable' by the time when trx_rollback_for_mysql(trx);
log_buffer_flush_to_disk() returns. In the } else {
logical sense the commit in the file-based /* The following call commits the
data structures happens here. */ mini-transaction, making the data dictionary
trx_commit_low(trx, &mtr); transaction committed at mtr.end_lsn. The
transaction becomes 'durable' by the time when
log_buffer_flush_to_disk() returns. In the
logical sense the commit in the file-based
data structures happens here. */
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
ut_ad(trx->insert_undo || trx->update_undo);
trx_commit_low(trx, &mtr);
}
/* If server crashes here, the dictionary in /* If server crashes here, the dictionary in
InnoDB and MySQL will differ. The .ibd files InnoDB and MySQL will differ. The .ibd files
...@@ -5745,7 +5831,6 @@ ha_innobase::commit_inplace_alter_table( ...@@ -5745,7 +5831,6 @@ ha_innobase::commit_inplace_alter_table(
update the in-memory structures, close some handles, release update the in-memory structures, close some handles, release
temporary files, and (unless we rolled back) update persistent temporary files, and (unless we rolled back) update persistent
statistics. */ statistics. */
dberr_t error = DB_SUCCESS;
for (inplace_alter_handler_ctx** pctx = ctx_array; for (inplace_alter_handler_ctx** pctx = ctx_array;
*pctx; pctx++) { *pctx; pctx++) {
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
...@@ -672,6 +672,21 @@ fil_discard_tablespace( ...@@ -672,6 +672,21 @@ fil_discard_tablespace(
ulint id) /*!< in: space id */ ulint id) /*!< in: space id */
__attribute__((warn_unused_result)); __attribute__((warn_unused_result));
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/** Test if a tablespace file can be renamed to a new filepath by checking
if that the old filepath exists and the new filepath does not exist.
@param[in] space_id tablespace id
@param[in] old_path old filepath
@param[in] new_path new filepath
@param[in] is_discarded whether the tablespace is discarded
@return innodb error code */
dberr_t
fil_rename_tablespace_check(
ulint space_id,
const char* old_path,
const char* new_path,
bool is_discarded);
/*******************************************************************//** /*******************************************************************//**
Renames a single-table tablespace. The tablespace must be cached in the Renames a single-table tablespace. The tablespace must be cached in the
tablespace memory cache. tablespace memory cache.
...@@ -1168,21 +1183,19 @@ fil_get_space_names( ...@@ -1168,21 +1183,19 @@ fil_get_space_names(
/*!< in/out: Vector for collecting the names. */ /*!< in/out: Vector for collecting the names. */
__attribute__((warn_unused_result)); __attribute__((warn_unused_result));
/****************************************************************//** /** Generate redo log for swapping two .ibd files
Generate redo logs for swapping two .ibd files */ @param[in] old_table old table
@param[in] new_table new table
@param[in] tmp_name temporary table name
@param[in,out] mtr mini-transaction
@return innodb error code */
UNIV_INTERN UNIV_INTERN
void dberr_t
fil_mtr_rename_log( fil_mtr_rename_log(
/*===============*/ const dict_table_t* old_table,
ulint old_space_id, /*!< in: tablespace id of the old const dict_table_t* new_table,
table. */ const char* tmp_name,
const char* old_name, /*!< in: old table name */ mtr_t* mtr)
ulint new_space_id, /*!< in: tablespace id of the new
table */
const char* new_name, /*!< in: new table name */
const char* tmp_name, /*!< in: temp table name used while
swapping */
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull)); __attribute__((nonnull));
/*******************************************************************//** /*******************************************************************//**
......
...@@ -827,6 +827,10 @@ not_consistent: ...@@ -827,6 +827,10 @@ not_consistent:
fprintf(stderr, fprintf(stderr,
"InnoDB: No valid checkpoint found.\n" "InnoDB: No valid checkpoint found.\n"
"InnoDB: If you are attempting downgrade"
" from MySQL 5.7.9 or later,\n"
"InnoDB: please refer to " REFMAN
"upgrading-downgrading.html\n"
"InnoDB: If this error appears when you are" "InnoDB: If this error appears when you are"
" creating an InnoDB database,\n" " creating an InnoDB database,\n"
"InnoDB: the problem may be that during" "InnoDB: the problem may be that during"
......
...@@ -2068,8 +2068,20 @@ PageConverter::validate( ...@@ -2068,8 +2068,20 @@ PageConverter::validate(
return(IMPORT_PAGE_STATUS_CORRUPTED); return(IMPORT_PAGE_STATUS_CORRUPTED);
} else if (offset > 0 && page_get_page_no(page) == 0) { } else if (offset > 0 && page_get_page_no(page) == 0) {
const byte* b = page; ulint checksum;
const byte* e = b + m_page_size;
checksum = mach_read_from_4(page + FIL_PAGE_SPACE_OR_CHKSUM);
if (checksum != 0) {
/* Checksum check passed in buf_page_is_corrupted(). */
ib_logf(IB_LOG_LEVEL_WARN,
"%s: Page %lu checksum %lu should be zero.",
m_filepath, (ulong) (offset / m_page_size),
checksum);
}
const byte* b = page + FIL_PAGE_OFFSET;
const byte* e = page + m_page_size
- FIL_PAGE_END_LSN_OLD_CHKSUM;
/* If the page number is zero and offset > 0 then /* If the page number is zero and offset > 0 then
the entire page MUST consist of zeroes. If not then the entire page MUST consist of zeroes. If not then
......
...@@ -1454,6 +1454,7 @@ row_log_table_apply_insert_low( ...@@ -1454,6 +1454,7 @@ row_log_table_apply_insert_low(
dtuple_t* entry; dtuple_t* entry;
const row_log_t*log = dup->index->online_log; const row_log_t*log = dup->index->online_log;
dict_index_t* index = dict_table_get_first_index(log->table); dict_index_t* index = dict_table_get_first_index(log->table);
ulint n_index = 0;
ut_ad(dtuple_validate(row)); ut_ad(dtuple_validate(row));
ut_ad(trx_id); ut_ad(trx_id);
...@@ -1489,6 +1490,8 @@ row_log_table_apply_insert_low( ...@@ -1489,6 +1490,8 @@ row_log_table_apply_insert_low(
} }
do { do {
n_index++;
if (!(index = dict_table_get_next_index(index))) { if (!(index = dict_table_get_next_index(index))) {
break; break;
} }
...@@ -1501,6 +1504,12 @@ row_log_table_apply_insert_low( ...@@ -1501,6 +1504,12 @@ row_log_table_apply_insert_low(
error = row_ins_sec_index_entry_low( error = row_ins_sec_index_entry_low(
flags, BTR_MODIFY_TREE, flags, BTR_MODIFY_TREE,
index, offsets_heap, heap, entry, trx_id, thr); index, offsets_heap, heap, entry, trx_id, thr);
/* Report correct index name for duplicate key error. */
if (error == DB_DUPLICATE_KEY) {
thr_get_trx(thr)->error_key_num = n_index;
}
} while (error == DB_SUCCESS); } while (error == DB_SUCCESS);
return(error); return(error);
...@@ -1808,6 +1817,7 @@ row_log_table_apply_update( ...@@ -1808,6 +1817,7 @@ row_log_table_apply_update(
mtr_t mtr; mtr_t mtr;
btr_pcur_t pcur; btr_pcur_t pcur;
dberr_t error; dberr_t error;
ulint n_index = 0;
ut_ad(dtuple_get_n_fields_cmp(old_pk) ut_ad(dtuple_get_n_fields_cmp(old_pk)
== dict_index_get_n_unique(index)); == dict_index_get_n_unique(index));
...@@ -2083,6 +2093,8 @@ func_exit_committed: ...@@ -2083,6 +2093,8 @@ func_exit_committed:
break; break;
} }
n_index++;
if (index->type & DICT_FTS) { if (index->type & DICT_FTS) {
continue; continue;
} }
...@@ -2126,6 +2138,11 @@ func_exit_committed: ...@@ -2126,6 +2138,11 @@ func_exit_committed:
BTR_MODIFY_TREE, index, offsets_heap, heap, BTR_MODIFY_TREE, index, offsets_heap, heap,
entry, trx_id, thr); entry, trx_id, thr);
/* Report correct index name for duplicate key error. */
if (error == DB_DUPLICATE_KEY) {
thr_get_trx(thr)->error_key_num = n_index;
}
mtr_start(&mtr); mtr_start(&mtr);
} }
......
...@@ -158,6 +158,9 @@ static const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES = ...@@ -158,6 +158,9 @@ static const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES =
#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD #define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
#define SRV_MAX_N_PENDING_SYNC_IOS 100 #define SRV_MAX_N_PENDING_SYNC_IOS 100
/** The round off to MB is similar as done in srv_parse_megabytes() */
#define CALC_NUMBER_OF_PAGES(size) ((size) / (1024 * 1024)) * \
((1024 * 1024) / (UNIV_PAGE_SIZE))
#ifdef UNIV_PFS_THREAD #ifdef UNIV_PFS_THREAD
/* Keys to register InnoDB threads with performance schema */ /* Keys to register InnoDB threads with performance schema */
UNIV_INTERN mysql_pfs_key_t io_handler_thread_key; UNIV_INTERN mysql_pfs_key_t io_handler_thread_key;
...@@ -967,10 +970,16 @@ open_or_create_data_files( ...@@ -967,10 +970,16 @@ open_or_create_data_files(
size_check: size_check:
size = os_file_get_size(files[i]); size = os_file_get_size(files[i]);
ut_a(size != (os_offset_t) -1); ut_a(size != (os_offset_t) -1);
/* Round size downward to megabytes */
rounded_size_pages = (ulint) /* Under some error conditions like disk full
(size >> UNIV_PAGE_SIZE_SHIFT); narios or file size reaching filesystem
limit the data file could contain an incomplete
extent at the end. When we extend a data file
and if some failure happens, then also the data
file could contain an incomplete extent. So we
need to round the size downward to a megabyte.*/
rounded_size_pages = (ulint) CALC_NUMBER_OF_PAGES(size);
if (i == srv_n_data_files - 1 if (i == srv_n_data_files - 1
&& srv_auto_extend_last_data_file) { && srv_auto_extend_last_data_file) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment