diff options
author | Igor Babaev <igor@askmonty.org> | 2018-11-10 14:52:57 -0800 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2018-11-10 14:52:57 -0800 |
commit | 5f46670bd09babbee75a24ac82eb4ade0706da66 (patch) | |
tree | 85e2759b75650b8165c3e01638e9458eb4d1274c /storage/innobase/row/row0log.cc | |
parent | 8d5a11122c32f4d9eb87536886c6e893377bdd07 (diff) | |
parent | 3ea7de9a78a1410a9b79362774247e9e44b201b3 (diff) | |
download | mariadb-git-5f46670bd09babbee75a24ac82eb4ade0706da66.tar.gz |
Merge branch '10.4' into 10.4-mdev16188
Diffstat (limited to 'storage/innobase/row/row0log.cc')
-rw-r--r-- | storage/innobase/row/row0log.cc | 120 |
1 files changed, 86 insertions, 34 deletions
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index db33910c6f2..07772fc5468 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -227,6 +227,8 @@ struct row_log_t { table could be emptied, so that table->is_instant() no longer holds, but all log records must be in the "instant" format. */ unsigned n_core_fields; + /** the default values of non-core fields when the operation started */ + dict_col_t::def_t* non_core_fields; bool allow_not_null; /*!< Whether the alter ignore is being used or if the sql mode is non-strict mode; if not, NULL values will not be converted to @@ -243,6 +245,14 @@ struct row_log_t { ut_ad(n_core_fields <= index->n_fields); return n_core_fields != index->n_fields; } + + const byte* instant_field_value(ulint n, ulint* len) const + { + ut_ad(n >= n_core_fields); + const dict_col_t::def_t& d= non_core_fields[n - n_core_fields]; + *len = d.len; + return static_cast<const byte*>(d.data); + } }; /** Create the file or online log if it does not exist. @@ -674,9 +684,9 @@ row_log_table_delete( fields of the record. */ heap = mem_heap_create( DATA_TRX_ID_LEN - + DTUPLE_EST_ALLOC(unsigned(new_index->n_uniq) + 2)); - old_pk = tuple = dtuple_create( - heap, unsigned(new_index->n_uniq) + 2); + + DTUPLE_EST_ALLOC(new_index->first_user_field())); + old_pk = tuple = dtuple_create(heap, + new_index->first_user_field()); dict_index_copy_types(tuple, new_index, tuple->n_fields); dtuple_set_n_fields_cmp(tuple, new_index->n_uniq); @@ -841,7 +851,7 @@ row_log_table_low_redundant( const bool is_instant = index->online_log->is_instant(index); rec_comp_status_t status = is_instant - ? REC_STATUS_COLUMNS_ADDED : REC_STATUS_ORDINARY; + ? REC_STATUS_INSTANT : REC_STATUS_ORDINARY; size = rec_get_converted_size_temp( index, tuple->fields, tuple->n_fields, &extra_size, status); @@ -895,7 +905,7 @@ row_log_table_low_redundant( *b++ = static_cast<byte>(extra_size); } - if (status == REC_STATUS_COLUMNS_ADDED) { + if (status == REC_STATUS_INSTANT) { ut_ad(is_instant); if (n_fields <= index->online_log->n_core_fields) { status = REC_STATUS_ORDINARY; @@ -935,15 +945,16 @@ row_log_table_low( ulint mrec_size; ulint avail_size; const dict_index_t* new_index; + row_log_t* log = index->online_log; - new_index = dict_table_get_first_index(index->online_log->table); + new_index = dict_table_get_first_index(log->table); ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(new_index)); ut_ad(!dict_index_is_online_ddl(new_index)); ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_n_fields(offsets) == dict_index_get_n_fields(index)); - ut_ad(rec_offs_size(offsets) <= sizeof index->online_log->tail.buf); + ut_ad(rec_offs_size(offsets) <= sizeof log->tail.buf); ut_ad(rw_lock_own_flagged( &index->lock, RW_LOCK_FLAG_S | RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX)); @@ -959,7 +970,7 @@ row_log_table_low( ut_ad(!"wrong page type"); } #endif /* UNIV_DEBUG */ - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); ut_ad(page_rec_is_leaf(rec)); ut_ad(!page_is_comp(page_align(rec)) == !rec_offs_comp(offsets)); /* old_pk=row_log_table_get_pk() [not needed in INSERT] is a prefix @@ -970,7 +981,7 @@ row_log_table_low( if (index->online_status != ONLINE_INDEX_CREATION || (index->type & DICT_CORRUPT) || index->table->corrupted - || index->online_log->error != DB_SUCCESS) { + || log->error != DB_SUCCESS) { return; } @@ -982,19 +993,37 @@ row_log_table_low( ut_ad(page_is_comp(page_align(rec))); ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY - || rec_get_status(rec) == REC_STATUS_COLUMNS_ADDED); + || rec_get_status(rec) == REC_STATUS_INSTANT); const ulint omit_size = REC_N_NEW_EXTRA_BYTES; const ulint rec_extra_size = rec_offs_extra_size(offsets) - omit_size; - const bool is_instant = index->online_log->is_instant(index); + const bool is_instant = log->is_instant(index); extra_size = rec_extra_size + is_instant; + unsigned fake_extra_size = 0; + byte fake_extra_buf[2]; + if (is_instant && UNIV_UNLIKELY(!index->is_instant())) { + /* The source table was emptied after ALTER TABLE + started, and it was converted to non-instant format. + Because row_log_table_apply_op() expects to find + all records to be logged in the same way, we will + be unable to copy the rec_extra_size bytes from the + record header, but must convert them here. */ + unsigned n_add = index->n_fields - 1 - log->n_core_fields; + fake_extra_size = rec_get_n_add_field_len(n_add); + ut_ad(fake_extra_size == 1 || fake_extra_size == 2); + extra_size += fake_extra_size; + byte* fake_extra = fake_extra_buf + fake_extra_size - 1; + rec_set_n_add_field(fake_extra, n_add); + ut_ad(fake_extra + 1 == fake_extra_buf); + } + mrec_size = ROW_LOG_HEADER_SIZE + (extra_size >= 0x80) + rec_offs_size(offsets) - omit_size - + is_instant; + + is_instant + fake_extra_size; - if (insert || index->online_log->same_pk) { + if (insert || log->same_pk) { ut_ad(!old_pk); old_pk_extra_size = old_pk_size = 0; } else { @@ -1012,8 +1041,7 @@ row_log_table_low( mrec_size += 1/*old_pk_extra_size*/ + old_pk_size; } - if (byte* b = row_log_table_open(index->online_log, - mrec_size, &avail_size)) { + if (byte* b = row_log_table_open(log, mrec_size, &avail_size)) { if (insert) { *b++ = ROW_T_INSERT; } else { @@ -1038,20 +1066,23 @@ row_log_table_low( } if (is_instant) { - *b++ = rec_get_status(rec); + *b++ = fake_extra_size + ? REC_STATUS_INSTANT + : rec_get_status(rec); } else { ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY); } memcpy(b, rec - rec_extra_size - omit_size, rec_extra_size); b += rec_extra_size; + memcpy(b, fake_extra_buf, fake_extra_size); + b += fake_extra_size; ulint len; ulint trx_id_offs = rec_get_nth_field_offs( offsets, index->n_uniq, &len); ut_ad(len == DATA_TRX_ID_LEN); memcpy(b, rec, rec_offs_data_size(offsets)); - if (trx_read_trx_id(b + trx_id_offs) - < index->online_log->min_trx) { + if (trx_read_trx_id(b + trx_id_offs) < log->min_trx) { memcpy(b + trx_id_offs, reset_trx_id, sizeof reset_trx_id); } @@ -1133,7 +1164,6 @@ row_log_table_get_pk_col( field = rec_get_nth_field(rec, offsets, i, &len); if (len == UNIV_SQL_NULL) { - if (!log->allow_not_null) { return(DB_INVALID_NULL); } @@ -1142,6 +1172,9 @@ row_log_table_get_pk_col( field = static_cast<const byte*>( log->defaults->fields[n_default_cols].data); + if (!field) { + return(DB_INVALID_NULL); + } len = log->defaults->fields[i - DATA_N_SYS_COLS].len; } @@ -1526,11 +1559,17 @@ row_log_table_apply_convert_mrec( const dict_col_t* col = dict_field_get_col(ind_field); + if (col->is_dropped()) { + /* the column was instantly dropped earlier */ + ut_ad(index->table->instant); + continue; + } + ulint col_no = log->col_map[dict_col_get_no(col)]; if (col_no == ULINT_UNDEFINED) { - /* dropped column */ + /* the column is being dropped now */ continue; } @@ -1576,7 +1615,7 @@ blob_done: } else { data = rec_get_nth_field(mrec, offsets, i, &len); if (len == UNIV_SQL_DEFAULT) { - data = index->instant_field_value(i, &len); + data = log->instant_field_value(i, &len); } dfield_set_data(dfield, data, len); } @@ -1886,8 +1925,7 @@ row_log_table_apply_delete( btr_pcur_t pcur; ulint* offsets; - ut_ad(rec_offs_n_fields(moffsets) - == dict_index_get_n_unique(index) + 2); + ut_ad(rec_offs_n_fields(moffsets) == index->first_user_field()); ut_ad(!rec_offs_any_extern(moffsets)); /* Convert the row to a search tuple. */ @@ -2416,7 +2454,7 @@ row_log_table_apply_op( rec_offs_set_n_fields(offsets, dup->index->n_fields); rec_init_offsets_temp(mrec, dup->index, offsets, - log->n_core_fields, + log->n_core_fields, log->non_core_fields, is_instant ? static_cast<rec_comp_status_t>( *(mrec - extra_size)) @@ -2450,8 +2488,7 @@ row_log_table_apply_op( /* The ROW_T_DELETE record was converted by rec_convert_dtuple_to_temp() using new_index. */ ut_ad(!new_index->is_instant()); - rec_offs_set_n_fields(offsets, - unsigned(new_index->n_uniq) + 2); + rec_offs_set_n_fields(offsets, new_index->first_user_field()); rec_init_offsets_temp(mrec, new_index, offsets); next_mrec = mrec + rec_offs_data_size(offsets); if (next_mrec > mrec_end) { @@ -2497,6 +2534,7 @@ row_log_table_apply_op( rec_offs_set_n_fields(offsets, dup->index->n_fields); rec_init_offsets_temp(mrec, dup->index, offsets, log->n_core_fields, + log->non_core_fields, is_instant ? static_cast<rec_comp_status_t>( *(mrec - extra_size)) @@ -2542,7 +2580,7 @@ row_log_table_apply_op( rec_convert_dtuple_to_temp() using new_index. */ ut_ad(!new_index->is_instant()); rec_offs_set_n_fields(offsets, - unsigned(new_index->n_uniq) + 2); + new_index->first_user_field()); rec_init_offsets_temp(mrec, new_index, offsets); next_mrec = mrec + rec_offs_data_size(offsets); @@ -2552,13 +2590,12 @@ row_log_table_apply_op( /* Copy the PRIMARY KEY fields and DB_TRX_ID, DB_ROLL_PTR from mrec to old_pk. */ - old_pk = dtuple_create( - heap, unsigned(new_index->n_uniq) + 2); + old_pk = dtuple_create(heap, + new_index->first_user_field()); dict_index_copy_types(old_pk, new_index, old_pk->n_fields); - for (ulint i = 0; - i < dict_index_get_n_unique(new_index) + 2; + for (ulint i = 0; i < new_index->first_user_field(); i++) { const void* field; ulint len; @@ -2598,6 +2635,7 @@ row_log_table_apply_op( rec_offs_set_n_fields(offsets, dup->index->n_fields); rec_init_offsets_temp(mrec, dup->index, offsets, log->n_core_fields, + log->non_core_fields, is_instant ? static_cast<rec_comp_status_t>( *(mrec - extra_size)) @@ -2708,8 +2746,8 @@ row_log_table_apply_ops( dict_index_t* new_index = dict_table_get_first_index( new_table); const ulint i = 1 + REC_OFFS_HEADER_SIZE - + ut_max(dict_index_get_n_fields(index), - dict_index_get_n_unique(new_index) + 2); + + std::max<ulint>(index->n_fields, + new_index->first_user_field()); const ulint new_trx_id_col = dict_col_get_clust_pos( dict_table_get_sys_col(new_table, DATA_TRX_ID), new_index); trx_t* trx = thr_get_trx(thr); @@ -3169,11 +3207,24 @@ row_log_allocate( log->head.total = 0; log->path = path; log->n_core_fields = index->n_core_fields; - ut_ad(!table || log->is_instant(index) == index->is_instant()); + ut_ad(!table || log->is_instant(index) + == (index->n_core_fields < index->n_fields)); log->allow_not_null = allow_not_null; log->old_table = old_table; log->n_rows = 0; + if (table && index->is_instant()) { + const unsigned n = log->n_core_fields; + log->non_core_fields = UT_NEW_ARRAY_NOKEY( + dict_col_t::def_t, index->n_fields - n); + for (unsigned i = n; i < index->n_fields; i++) { + log->non_core_fields[i - n] + = index->fields[i].col->def_val; + } + } else { + log->non_core_fields = NULL; + } + dict_index_set_online_status(index, ONLINE_INDEX_CREATION); index->online_log = log; @@ -3206,6 +3257,7 @@ row_log_free( MONITOR_ATOMIC_DEC(MONITOR_ONLINE_CREATE_INDEX); UT_DELETE(log->blobs); + UT_DELETE_ARRAY(log->non_core_fields); row_log_block_free(log->tail); row_log_block_free(log->head); row_merge_file_destroy_low(log->fd); |