diff options
Diffstat (limited to 'storage/innobase/trx/trx0rec.cc')
-rw-r--r-- | storage/innobase/trx/trx0rec.cc | 101 |
1 files changed, 56 insertions, 45 deletions
diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index a2f08fdb074..595c2a15fb3 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -37,7 +37,6 @@ Created 3/26/1996 Heikki Tuuri #include "trx0purge.h" #include "trx0rseg.h" #include "row0row.h" -#include "fsp0sysspace.h" #include "row0mysql.h" /** The search tuple corresponding to TRX_UNDO_INSERT_METADATA. */ @@ -954,9 +953,7 @@ trx_undo_page_report_modify( *ptr++ = (byte) rec_get_info_bits(rec, dict_table_is_comp(table)); /* Store the values of the system columns */ - field = rec_get_nth_field(rec, offsets, - dict_index_get_sys_col_pos( - index, DATA_TRX_ID), &flen); + field = rec_get_nth_field(rec, offsets, index->db_trx_id(), &flen); ut_ad(flen == DATA_TRX_ID_LEN); trx_id = trx_read_trx_id(field); @@ -970,9 +967,7 @@ trx_undo_page_report_modify( } ptr += mach_u64_write_compressed(ptr, trx_id); - field = rec_get_nth_field(rec, offsets, - dict_index_get_sys_col_pos( - index, DATA_ROLL_PTR), &flen); + field = rec_get_nth_field(rec, offsets, index->db_roll_ptr(), &flen); ut_ad(flen == DATA_ROLL_PTR_LEN); ut_ad(memcmp(field, field_ref_zero, DATA_ROLL_PTR_LEN)); @@ -1340,6 +1335,8 @@ store_len: table, col); ut_a(prefix_len < sizeof ext_buf); + const page_size_t& page_size + = dict_table_page_size(table); /* If there is a spatial index on it, log its MBR */ @@ -1348,9 +1345,7 @@ store_len: col->mtype)); trx_undo_get_mbr_from_ext( - mbr, - dict_table_page_size( - table), + mbr, page_size, field, &flen); } @@ -1359,7 +1354,7 @@ store_len: flen < REC_ANTELOPE_MAX_INDEX_COL_LEN && !ignore_prefix ? ext_buf : NULL, prefix_len, - dict_table_page_size(table), + page_size, &field, &flen, spatial_status); } else { @@ -1553,7 +1548,6 @@ trx_undo_update_rec_get_update( upd_t* update; ulint n_fields; byte* buf; - ulint i; bool first_v_col = true; bool is_undo_log = true; ulint n_skip_field = 0; @@ -1566,7 +1560,7 @@ trx_undo_update_rec_get_update( n_fields = 0; } - update = upd_create(n_fields + 2, heap); + *upd = update = upd_create(n_fields + 2, heap); update->info_bits = info_bits; @@ -1578,9 +1572,7 @@ trx_undo_update_rec_get_update( mach_write_to_6(buf, trx_id); - upd_field_set_field_no(upd_field, - dict_index_get_sys_col_pos(index, DATA_TRX_ID), - index); + upd_field_set_field_no(upd_field, index->db_trx_id(), index); dfield_set_data(&(upd_field->new_val), buf, DATA_TRX_ID_LEN); upd_field = upd_get_nth_field(update, n_fields + 1); @@ -1589,15 +1581,12 @@ trx_undo_update_rec_get_update( trx_write_roll_ptr(buf, roll_ptr); - upd_field_set_field_no( - upd_field, dict_index_get_sys_col_pos(index, DATA_ROLL_PTR), - index); + upd_field_set_field_no(upd_field, index->db_roll_ptr(), index); dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN); /* Store then the updated ordinary columns to the update vector */ - for (i = 0; i < n_fields; i++) { - + for (ulint i = 0; i < n_fields; i++) { const byte* field; ulint len; ulint orig_len; @@ -1630,23 +1619,53 @@ trx_undo_update_rec_get_update( upd_field_set_v_field_no(upd_field, field_no, index); } else if (UNIV_UNLIKELY((update->info_bits & ~REC_INFO_DELETED_FLAG) - == REC_INFO_MIN_REC_FLAG) - && index->is_instant()) { + == REC_INFO_MIN_REC_FLAG)) { + ut_ad(type == TRX_UNDO_UPD_EXIST_REC); const ulint uf = index->first_user_field(); ut_ad(field_no >= uf); if (update->info_bits != REC_INFO_MIN_REC_FLAG) { + /* Generic instant ALTER TABLE */ if (field_no == uf) { upd_field->new_val.type .metadata_blob_init(); + } else if (field_no >= index->n_fields) { + /* This is reachable during + purge if the table was emptied + and converted to the canonical + format on a later ALTER TABLE. + In this case, + row_purge_upd_exist_or_extern() + would only be interested in + freeing any BLOBs that were + updated, that is, the metadata + BLOB above. Other BLOBs in + the metadata record are never + updated; they are for the + initial DEFAULT values of the + instantly added columns, and + they will never change. + + Note: if the table becomes + empty during ROLLBACK or is + empty during subsequent ALTER + TABLE, and btr_page_empty() is + called to re-create the root + page without the metadata + record, in that case we should + only free the latest version + of BLOBs in the record, + which purge would never touch. */ + field_no = REC_MAX_N_FIELDS; + n_skip_field++; } else { - ut_ad(field_no > uf); dict_col_copy_type( dict_index_get_nth_col( index, field_no - 1), &upd_field->new_val.type); } } else { + /* Instant ADD COLUMN...LAST */ dict_col_copy_type( dict_index_get_nth_col(index, field_no), @@ -1710,31 +1729,23 @@ trx_undo_update_rec_get_update( } } - /* In rare scenario, we could have skipped virtual column (as they - are dropped. We will regenerate a update vector and skip them */ - if (n_skip_field > 0) { - ulint n = 0; - ut_ad(n_skip_field <= n_fields); + /* We may have to skip dropped indexed virtual columns. + Also, we may have to trim the update vector of a metadata record + if dict_index_t::clear_instant_alter() was invoked on the table + later, and the number of fields no longer matches. */ - upd_t* new_update = upd_create( - n_fields + 2 - n_skip_field, heap); + if (n_skip_field) { + upd_field_t* d = upd_get_nth_field(update, 0); + const upd_field_t* const end = d + n_fields + 2; - for (i = 0; i < n_fields + 2; i++) { - upd_field = upd_get_nth_field(update, i); - - if (upd_field->field_no == REC_MAX_N_FIELDS) { - continue; + for (const upd_field_t* s = d; s != end; s++) { + if (s->field_no != REC_MAX_N_FIELDS) { + *d++ = *s; } - - upd_field_t* new_upd_field - = upd_get_nth_field(new_update, n); - *new_upd_field = *upd_field; - n++; } - ut_ad(n == n_fields + 2 - n_skip_field); - *upd = new_update; - } else { - *upd = update; + + ut_ad(d + n_skip_field == end); + update->n_fields = d - upd_get_nth_field(update, 0); } return(const_cast<byte*>(ptr)); |