diff options
Diffstat (limited to 'storage/innodb_plugin/row')
-rw-r--r-- | storage/innodb_plugin/row/row0ins.c | 5 | ||||
-rw-r--r-- | storage/innodb_plugin/row/row0merge.c | 104 | ||||
-rw-r--r-- | storage/innodb_plugin/row/row0mysql.c | 7 | ||||
-rw-r--r-- | storage/innodb_plugin/row/row0umod.c | 3 | ||||
-rw-r--r-- | storage/innodb_plugin/row/row0undo.c | 2 |
5 files changed, 94 insertions, 27 deletions
diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c index 92ce04774ea..7e81cf6ab2c 100644 --- a/storage/innodb_plugin/row/row0ins.c +++ b/storage/innodb_plugin/row/row0ins.c @@ -2265,7 +2265,10 @@ row_ins_index_entry( err = row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry, n_ext, thr); if (err != DB_FAIL) { - + if (index == dict_table_get_first_index(index->table) + && thr_get_trx(thr)->mysql_thd != 0) { + DEBUG_SYNC_C("row_ins_clust_index_entry_leaf_after"); + } return(err); } diff --git a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c index 5da2a4b8534..63e14e6568f 100644 --- a/storage/innodb_plugin/row/row0merge.c +++ b/storage/innodb_plugin/row/row0merge.c @@ -291,6 +291,7 @@ row_merge_buf_add( const dict_field_t* ifield; const dict_col_t* col; ulint col_no; + ulint fixed_len; const dfield_t* row_field; ulint len; @@ -340,9 +341,21 @@ row_merge_buf_add( ut_ad(len <= col->len || col->mtype == DATA_BLOB); - if (ifield->fixed_len) { - ut_ad(len == ifield->fixed_len); + fixed_len = ifield->fixed_len; + if (fixed_len && !dict_table_is_comp(index->table) + && col->mbminlen != col->mbmaxlen) { + /* CHAR in ROW_FORMAT=REDUNDANT is always + fixed-length, but in the temporary file it is + variable-length for variable-length character + sets. */ + fixed_len = 0; + } + + if (fixed_len) { + ut_ad(len == fixed_len); ut_ad(!dfield_is_ext(field)); + ut_ad(!col->mbmaxlen || len >= col->mbminlen + * (fixed_len / col->mbmaxlen)); } else if (dfield_is_ext(field)) { extra_size += 2; } else if (len < 128 @@ -363,12 +376,11 @@ row_merge_buf_add( ulint size; ulint extra; - size = rec_get_converted_size_comp(index, - REC_STATUS_ORDINARY, - entry, n_fields, &extra); + size = rec_get_converted_size_temp( + index, entry, n_fields, &extra); - ut_ad(data_size + extra_size + REC_N_NEW_EXTRA_BYTES == size); - ut_ad(extra_size + REC_N_NEW_EXTRA_BYTES == extra); + ut_ad(data_size + extra_size == size); + ut_ad(extra_size == extra); } #endif /* UNIV_DEBUG */ @@ -572,14 +584,9 @@ row_merge_buf_write( ulint extra_size; const dfield_t* entry = buf->tuples[i]; - size = rec_get_converted_size_comp(index, - REC_STATUS_ORDINARY, - entry, n_fields, - &extra_size); + size = rec_get_converted_size_temp( + index, entry, n_fields, &extra_size); ut_ad(size >= extra_size); - ut_ad(extra_size >= REC_N_NEW_EXTRA_BYTES); - extra_size -= REC_N_NEW_EXTRA_BYTES; - size -= REC_N_NEW_EXTRA_BYTES; /* Encode extra_size + 1 */ if (extra_size + 1 < 0x80) { @@ -592,9 +599,8 @@ row_merge_buf_write( ut_ad(b + size < block[1]); - rec_convert_dtuple_to_rec_comp(b + extra_size, 0, index, - REC_STATUS_ORDINARY, - entry, n_fields); + rec_convert_dtuple_to_temp(b + extra_size, index, + entry, n_fields); b += size; @@ -696,6 +702,8 @@ row_merge_read( ib_uint64_t ofs = ((ib_uint64_t) offset) * sizeof *buf; ibool success; + DBUG_EXECUTE_IF("row_merge_read_failure", return(FALSE);); + #ifdef UNIV_DEBUG if (row_merge_print_block_read) { fprintf(stderr, "row_merge_read fd=%d ofs=%lu\n", @@ -732,6 +740,8 @@ row_merge_write( ib_uint64_t ofs = ((ib_uint64_t) offset) * sizeof(row_merge_block_t); + DBUG_EXECUTE_IF("row_merge_write_failure", return(FALSE);); + #ifdef UNIV_DEBUG if (row_merge_print_block_write) { fprintf(stderr, "row_merge_write fd=%d ofs=%lu\n", @@ -841,7 +851,7 @@ err_exit: *mrec = *buf + extra_size; - rec_init_offsets_comp_ordinary(*mrec, 0, index, offsets); + rec_init_offsets_temp(*mrec, index, offsets); data_size = rec_offs_data_size(offsets); @@ -860,7 +870,7 @@ err_exit: *mrec = b + extra_size; - rec_init_offsets_comp_ordinary(*mrec, 0, index, offsets); + rec_init_offsets_temp(*mrec, index, offsets); data_size = rec_offs_data_size(offsets); ut_ad(extra_size + data_size < sizeof *buf); @@ -2183,9 +2193,10 @@ row_merge_drop_temp_indexes(void) } /*********************************************************************//** -Create a merge file. */ -static -void +Create a merge file. +@return file descriptor, or -1 on failure */ +static __attribute__((nonnull, warn_unused_result)) +int row_merge_file_create( /*==================*/ merge_file_t* merge_file) /*!< out: merge file structure */ @@ -2193,6 +2204,7 @@ row_merge_file_create( merge_file->fd = innobase_mysql_tmpfile(); merge_file->offset = 0; merge_file->n_rec = 0; + return(merge_file->fd); } /*********************************************************************//** @@ -2418,6 +2430,28 @@ row_merge_rename_tables( goto err_exit; } + /* Generate the redo logs for file operations */ + fil_mtr_rename_log(old_table->space, old_name, + new_table->space, new_table->name, tmp_name); + + /* What if the redo logs are flushed to disk here? This is + tested with following crash point */ + DBUG_EXECUTE_IF("bug14669848_precommit", log_buffer_flush_to_disk(); + DBUG_SUICIDE();); + + /* File operations cannot be rolled back. So, before proceeding + with file operations, commit the dictionary changes.*/ + trx_commit_for_mysql(trx); + + /* If server crashes here, the dictionary in InnoDB and MySQL + will differ. The .ibd files and the .frm files must be swapped + manually by the administrator. No loss of data. */ + DBUG_EXECUTE_IF("bug14669848", DBUG_SUICIDE();); + + /* Ensure that the redo logs are flushed to disk. The config + innodb_flush_log_at_trx_commit must not affect this. */ + log_buffer_flush_to_disk(); + /* The following calls will also rename the .ibd data files if the tables are stored in a single-table tablespace */ @@ -2591,7 +2625,7 @@ row_merge_build_indexes( ulint block_size; ulint i; ulint error; - int tmpfd; + int tmpfd = -1; ut_ad(trx); ut_ad(old_table); @@ -2608,13 +2642,31 @@ row_merge_build_indexes( block_size = 3 * sizeof *block; block = os_mem_alloc_large(&block_size); + /* Initialize all the merge file descriptors, so that we + don't call row_merge_file_destroy() on uninitialized + merge file descriptor */ + + for (i = 0; i < n_indexes; i++) { + merge_files[i].fd = -1; + } + for (i = 0; i < n_indexes; i++) { - row_merge_file_create(&merge_files[i]); + if (row_merge_file_create(&merge_files[i]) < 0) + { + error = DB_OUT_OF_MEMORY; + goto func_exit; + } } tmpfd = innobase_mysql_tmpfile(); + if (tmpfd < 0) + { + error = DB_OUT_OF_MEMORY; + goto func_exit; + } + /* Reset the MySQL row buffer that is used when reporting duplicate keys. */ innobase_rec_reset(table); @@ -2655,7 +2707,9 @@ row_merge_build_indexes( } func_exit: - close(tmpfd); + if (tmpfd >= 0) { + close(tmpfd); + } for (i = 0; i < n_indexes; i++) { row_merge_file_destroy(&merge_files[i]); diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index 137a164c4cd..9379912a218 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -4083,6 +4083,13 @@ end: trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, NULL); trx->error_state = DB_SUCCESS; + } else { + if (old_is_tmp && !new_is_tmp) { + /* After ALTER TABLE the table statistics + needs to be rebuilt. It will be rebuilt + when the table is loaded again. */ + table->stat_initialized = FALSE; + } } } diff --git a/storage/innodb_plugin/row/row0umod.c b/storage/innodb_plugin/row/row0umod.c index 31f7c9f4888..a1c86424625 100644 --- a/storage/innodb_plugin/row/row0umod.c +++ b/storage/innodb_plugin/row/row0umod.c @@ -493,6 +493,7 @@ row_undo_mod_upd_del_sec( ulint err = DB_SUCCESS; ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC); + ut_ad(!node->undo_row); heap = mem_heap_create(1024); while (node->index != NULL) { @@ -546,6 +547,8 @@ row_undo_mod_del_mark_sec( dict_index_t* index; ulint err; + ut_ad(!node->undo_row); + heap = mem_heap_create(1024); while (node->index != NULL) { diff --git a/storage/innodb_plugin/row/row0undo.c b/storage/innodb_plugin/row/row0undo.c index b1606bda5ef..f07d8013919 100644 --- a/storage/innodb_plugin/row/row0undo.c +++ b/storage/innodb_plugin/row/row0undo.c @@ -217,7 +217,7 @@ row_undo_search_clust_to_pcur( node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets, NULL, ext, node->heap); - if (node->update) { + if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) { node->undo_row = dtuple_copy(node->row, node->heap); row_upd_replace(node->undo_row, &node->undo_ext, clust_index, node->update, node->heap); |