diff options
Diffstat (limited to 'storage/xtradb/row')
-rw-r--r-- | storage/xtradb/row/row0import.cc | 16 | ||||
-rw-r--r-- | storage/xtradb/row/row0log.cc | 17 | ||||
-rw-r--r-- | storage/xtradb/row/row0merge.cc | 157 | ||||
-rw-r--r-- | storage/xtradb/row/row0mysql.cc | 50 |
4 files changed, 162 insertions, 78 deletions
diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index ac6380e5a27..893ffcab3da 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -2070,8 +2070,20 @@ PageConverter::validate( return(IMPORT_PAGE_STATUS_CORRUPTED); } else if (offset > 0 && page_get_page_no(page) == 0) { - const byte* b = page; - const byte* e = b + m_page_size; + ulint checksum; + + 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 the entire page MUST consist of zeroes. If not then diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc index 7014b8b99d2..b0c6f881f81 100644 --- a/storage/xtradb/row/row0log.cc +++ b/storage/xtradb/row/row0log.cc @@ -1462,6 +1462,7 @@ row_log_table_apply_insert_low( dtuple_t* entry; const row_log_t*log = dup->index->online_log; dict_index_t* index = dict_table_get_first_index(log->table); + ulint n_index = 0; ut_ad(dtuple_validate(row)); ut_ad(trx_id); @@ -1497,6 +1498,8 @@ row_log_table_apply_insert_low( } do { + n_index++; + if (!(index = dict_table_get_next_index(index))) { break; } @@ -1509,6 +1512,12 @@ row_log_table_apply_insert_low( error = row_ins_sec_index_entry_low( flags, BTR_MODIFY_TREE, 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); return(error); @@ -1816,6 +1825,7 @@ row_log_table_apply_update( mtr_t mtr; btr_pcur_t pcur; dberr_t error; + ulint n_index = 0; ut_ad(dtuple_get_n_fields_cmp(old_pk) == dict_index_get_n_unique(index)); @@ -2091,6 +2101,8 @@ func_exit_committed: break; } + n_index++; + if (index->type & DICT_FTS) { continue; } @@ -2134,6 +2146,11 @@ func_exit_committed: BTR_MODIFY_TREE, 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; + } + mtr_start(&mtr); } diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index ad3e7619c8a..8d7fcd7388c 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/row/row0merge.cc @@ -1,7 +1,6 @@ /***************************************************************************** Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2015, 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 @@ -971,7 +970,6 @@ row_merge_read( success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf, ofs, srv_sort_buf_size); - srv_stats.merge_buffers_read.inc(); /* For encrypted tables, decrypt data after reading and copy data */ if (crypt_data && crypt_buf) { @@ -1027,7 +1025,6 @@ row_merge_write( } ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), out_buf, ofs, buf_len); - srv_stats.merge_buffers_written.inc(); #ifdef UNIV_DEBUG if (row_merge_print_block_write) { @@ -1916,7 +1913,7 @@ write_buffers: /* We have enough data tuples to form a block. Sort them and write to disk. */ - if (UNIV_LIKELY(buf->n_tuples)) { + if (buf->n_tuples) { if (dict_index_is_unique(buf->index)) { row_merge_dup_t dup = { buf->index, table, col_map, 0}; @@ -1957,17 +1954,13 @@ write_buffers: dict_index_get_lock(buf->index)); } - /* Do not write empty buffers to temporary file */ - if (buf->n_tuples) { - - row_merge_buf_write(buf, file, block); + row_merge_buf_write(buf, file, block); - if (!row_merge_write(file->fd, file->offset++, block, - crypt_data, crypt_block, new_table->space)) { - err = DB_TEMP_FILE_WRITE_FAILURE; - trx->error_key_num = i; - break; - } + if (!row_merge_write(file->fd, file->offset++, block, + crypt_data, crypt_block, new_table->space)) { + err = DB_TEMP_FILE_WRITE_FAILURE; + trx->error_key_num = i; + break; } UNIV_MEM_INVALID(&block[0], srv_sort_buf_size); @@ -2284,8 +2277,6 @@ done1: b2, of->fd, &of->offset, crypt_data, crypt_block ? &crypt_block[2 * srv_sort_buf_size] : NULL, space); - srv_stats.merge_buffers_merged.inc(); - return(b2 ? DB_SUCCESS : DB_CORRUPTION); } @@ -3746,8 +3737,11 @@ row_merge_create_index( /*===================*/ trx_t* trx, /*!< in/out: trx (sets error_state) */ dict_table_t* table, /*!< in: the index is on this table */ - const index_def_t* index_def) + const index_def_t* index_def, /*!< in: the index definition */ + const char** col_names) + /*! in: column names if columns are + renamed or NULL */ { dict_index_t* index; dberr_t err; @@ -3767,9 +3761,24 @@ row_merge_create_index( for (i = 0; i < n_fields; i++) { index_field_t* ifield = &index_def->fields[i]; - const char * col_name = ifield->col_name ? - dict_table_get_col_name_for_mysql(table, ifield->col_name) : - dict_table_get_col_name(table, ifield->col_no); + const char * col_name; + + /* + Alter table renaming a column and then adding a index + to this new name e.g ALTER TABLE t + CHANGE COLUMN b c INT NOT NULL, ADD UNIQUE INDEX (c); + requires additional check as column names are not yet + changed when new index definitions are created. Table's + new column names are on a array of column name pointers + if any of the column names are changed. */ + + if (col_names && col_names[i]) { + col_name = col_names[i]; + } else { + col_name = ifield->col_name ? + dict_table_get_col_name_for_mysql(table, ifield->col_name) : + dict_table_get_col_name(table, ifield->col_no); + } dict_mem_index_add_field( index, @@ -4110,71 +4119,67 @@ wait_again: #ifdef FTS_INTERNAL_DIAG_PRINT DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n"); #endif - } else { - /* Sorting and inserting is required only if - there really is records */ - if (UNIV_LIKELY(merge_files[i].n_rec)) { - char buf[3 * NAME_LEN]; - char *bufend; - row_merge_dup_t dup = { - sort_idx, table, col_map, 0}; + } else if (UNIV_LIKELY(merge_files[i].n_rec)) { + char buf[3 * NAME_LEN]; + char *bufend; + row_merge_dup_t dup = { + sort_idx, table, col_map, 0}; - pct_cost = (COST_BUILD_INDEX_STATIC + - (total_dynamic_cost * merge_files[i].offset / - total_index_blocks)) / - (total_static_cost + total_dynamic_cost) - * PCT_COST_MERGESORT_INDEX * 100; + pct_cost = (COST_BUILD_INDEX_STATIC + + (total_dynamic_cost * merge_files[i].offset / + total_index_blocks)) / + (total_static_cost + total_dynamic_cost) + * PCT_COST_MERGESORT_INDEX * 100; + + bufend = innobase_convert_name(buf, sizeof buf, + indexes[i]->name, strlen(indexes[i]->name), + trx ? trx->mysql_thd : NULL, + FALSE); - bufend = innobase_convert_name(buf, sizeof buf, - indexes[i]->name, strlen(indexes[i]->name), - trx ? trx->mysql_thd : NULL, - FALSE); + buf[bufend - buf]='\0'; - buf[bufend - buf]='\0'; + sql_print_information("InnoDB: Online DDL : Start merge-sorting" + " index %s (%lu / %lu), estimated cost : %2.4f", + buf, (i+1), n_indexes, pct_cost); - sql_print_information("InnoDB: Online DDL : Start merge-sorting" - " index %s (%lu / %lu), estimated cost : %2.4f", - buf, (i+1), n_indexes, pct_cost); + error = row_merge_sort( + trx, &dup, &merge_files[i], + block, &tmpfd, true, + pct_progress, pct_cost, + crypt_data, crypt_block, new_table->space); - error = row_merge_sort( - trx, &dup, &merge_files[i], - block, &tmpfd, true, - pct_progress, pct_cost, - crypt_data, crypt_block, new_table->space); + pct_progress += pct_cost; + + sql_print_information("InnoDB: Online DDL : End of " + " merge-sorting index %s (%lu / %lu)", + buf, (i+1), n_indexes); + + DBUG_EXECUTE_IF( + "ib_merge_wait_after_sort", + os_thread_sleep(20000000);); /* 20 sec */ + if (error == DB_SUCCESS) { + pct_cost = (COST_BUILD_INDEX_STATIC + + (total_dynamic_cost * merge_files[i].offset / + total_index_blocks)) / + (total_static_cost + total_dynamic_cost) * + PCT_COST_INSERT_INDEX * 100; + + sql_print_information("InnoDB: Online DDL : Start " + "building index %s (%lu / %lu), estimated " + "cost : %2.4f", buf, (i+1), + n_indexes, pct_cost); + + error = row_merge_insert_index_tuples( + trx->id, sort_idx, old_table, + merge_files[i].fd, block, + merge_files[i].n_rec, pct_progress, pct_cost, + crypt_data, crypt_block, new_table->space); pct_progress += pct_cost; - sql_print_information("InnoDB: Online DDL : End of " - " merge-sorting index %s (%lu / %lu)", + sql_print_information("InnoDB: Online DDL : " + "End of building index %s (%lu / %lu)", buf, (i+1), n_indexes); - - DBUG_EXECUTE_IF( - "ib_merge_wait_after_sort", - os_thread_sleep(20000000);); /* 20 sec */ - - if (error == DB_SUCCESS) { - pct_cost = (COST_BUILD_INDEX_STATIC + - (total_dynamic_cost * merge_files[i].offset / - total_index_blocks)) / - (total_static_cost + total_dynamic_cost) * - PCT_COST_INSERT_INDEX * 100; - - sql_print_information("InnoDB: Online DDL : Start " - "building index %s (%lu / %lu), estimated " - "cost : %2.4f", buf, (i+1), - n_indexes, pct_cost); - - error = row_merge_insert_index_tuples( - trx->id, sort_idx, old_table, - merge_files[i].fd, block, - merge_files[i].n_rec, pct_progress, pct_cost, - crypt_data, crypt_block, new_table->space); - pct_progress += pct_cost; - - sql_print_information("InnoDB: Online DDL : " - "End of building index %s (%lu / %lu)", - buf, (i+1), n_indexes); - } } } diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 55e685ac19c..9427b20daf9 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -4894,6 +4894,7 @@ row_rename_table_for_mysql( pars_info_t* info = NULL; int retry; bool aux_fts_rename = false; + char* is_part = NULL; ut_a(old_name != NULL); ut_a(new_name != NULL); @@ -4931,6 +4932,55 @@ row_rename_table_for_mysql( table = dict_table_open_on_name(old_name, dict_locked, FALSE, DICT_ERR_IGNORE_NONE); + /* We look for pattern #P# to see if the table is partitioned + MySQL table. */ +#ifdef __WIN__ + is_part = strstr((char *)old_name, (char *)"#p#"); +#else + is_part = strstr((char *)old_name, (char *)"#P#"); +#endif /* __WIN__ */ + + /* MySQL partition engine hard codes the file name + separator as "#P#". The text case is fixed even if + lower_case_table_names is set to 1 or 2. This is true + for sub-partition names as well. InnoDB always + normalises file names to lower case on Windows, this + can potentially cause problems when copying/moving + tables between platforms. + + 1) If boot against an installation from Windows + platform, then its partition table name could + be all be in lower case in system tables. So we + will need to check lower case name when load table. + + 2) If we boot an installation from other case + sensitive platform in Windows, we might need to + check the existence of table name without lowering + case them in the system table. */ + if (!table && + is_part && + innobase_get_lower_case_table_names() == 1) { + char par_case_name[MAX_FULL_NAME_LEN + 1]; +#ifndef __WIN__ + /* Check for the table using lower + case name, including the partition + separator "P" */ + memcpy(par_case_name, old_name, + strlen(old_name)); + par_case_name[strlen(old_name)] = 0; + innobase_casedn_str(par_case_name); +#else + /* On Windows platfrom, check + whether there exists table name in + system table whose name is + not being normalized to lower case */ + normalize_table_name_low( + par_case_name, old_name, FALSE); +#endif + table = dict_table_open_on_name(par_case_name, dict_locked, FALSE, + DICT_ERR_IGNORE_NONE); + } + if (!table) { err = DB_TABLE_NOT_FOUND; ut_print_timestamp(stderr); |