diff options
Diffstat (limited to 'storage/innobase/row/row0upd.cc')
-rw-r--r-- | storage/innobase/row/row0upd.cc | 213 |
1 files changed, 102 insertions, 111 deletions
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index d081c5c2122..db39b486d0e 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -122,7 +122,7 @@ row_upd_changes_first_fields_binary( Checks if index currently is mentioned as a referenced index in a foreign key constraint. -NOTE that since we do not hold dict_operation_lock when leaving the +NOTE that since we do not hold dict_sys.latch when leaving the function, it may be that the referencing table has been dropped when we leave this function: this function is only for heuristic use! @@ -289,7 +289,7 @@ row_upd_check_references_constraints( } /* NOTE that if the thread ends up waiting for a lock - we will release dict_operation_lock temporarily! + we will release dict_sys.latch temporarily! But the inc_fk_checks() protects foreign_table from being dropped while the check is running. */ @@ -397,7 +397,7 @@ wsrep_row_upd_check_foreign_constraints( } /* NOTE that if the thread ends up waiting for a lock - we will release dict_operation_lock temporarily! + we will release dict_sys.latch temporarily! But the counter on the table protects 'foreign' from being dropped while the check is running. */ @@ -495,39 +495,6 @@ row_upd_rec_sys_fields_in_recovery( } } -/*********************************************************************//** -Sets the trx id or roll ptr field of a clustered index entry. */ -void -row_upd_index_entry_sys_field( -/*==========================*/ - dtuple_t* entry, /*!< in/out: index entry, where the memory - buffers for sys fields are already allocated: - the function just copies the new values to - them */ - dict_index_t* index, /*!< in: clustered index */ - ulint type, /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */ - ib_uint64_t val) /*!< in: value to write */ -{ - dfield_t* dfield; - byte* field; - ulint pos; - - ut_ad(dict_index_is_clust(index)); - - pos = dict_index_get_sys_col_pos(index, type); - - dfield = dtuple_get_nth_field(entry, pos); - field = static_cast<byte*>(dfield_get_data(dfield)); - - if (type == DATA_TRX_ID) { - ut_ad(val > 0); - trx_write_trx_id(field, val); - } else { - ut_ad(type == DATA_ROLL_PTR); - trx_write_roll_ptr(field, val); - } -} - /***********************************************************//** Returns TRUE if row update changes size of some field in index or if some field to be updated is stored externally in rec or update. @@ -680,7 +647,7 @@ row_upd_rec_in_place( switch (rec_get_status(rec)) { case REC_STATUS_ORDINARY: break; - case REC_STATUS_COLUMNS_ADDED: + case REC_STATUS_INSTANT: ut_ad(index->is_instant()); break; case REC_STATUS_NODE_PTR: @@ -731,35 +698,6 @@ row_upd_rec_in_place( } /*********************************************************************//** -Writes into the redo log the values of trx id and roll ptr and enough info -to determine their positions within a clustered index record. -@return new pointer to mlog */ -byte* -row_upd_write_sys_vals_to_log( -/*==========================*/ - dict_index_t* index, /*!< in: clustered index */ - trx_id_t trx_id, /*!< in: transaction id */ - roll_ptr_t roll_ptr,/*!< in: roll ptr of the undo log record */ - byte* log_ptr,/*!< pointer to a buffer of size > 20 opened - in mlog */ - mtr_t* mtr MY_ATTRIBUTE((unused))) /*!< in: mtr */ -{ - ut_ad(dict_index_is_clust(index)); - ut_ad(mtr); - - log_ptr += mach_write_compressed(log_ptr, - dict_index_get_sys_col_pos( - index, DATA_TRX_ID)); - - trx_write_roll_ptr(log_ptr, roll_ptr); - log_ptr += DATA_ROLL_PTR_LEN; - - log_ptr += mach_u64_write_compressed(log_ptr, trx_id); - - return(log_ptr); -} - -/*********************************************************************//** Parses the log data of system field values. @return log data end or NULL */ byte* @@ -1052,7 +990,6 @@ row_upd_build_difference_binary( ulint len; upd_t* update; ulint n_diff; - ulint trx_id_pos; ulint offsets_[REC_OFFS_NORMAL_SIZE]; const ulint n_v_fld = dtuple_get_n_v_fields(entry); rec_offs_init(offsets_); @@ -1067,10 +1004,6 @@ row_upd_build_difference_binary( n_diff = 0; - trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); - ut_ad(dict_index_get_sys_col_pos(index, DATA_ROLL_PTR) - == trx_id_pos + 1); - if (!offsets) { offsets = rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &heap); @@ -1085,16 +1018,9 @@ row_upd_build_difference_binary( /* NOTE: we compare the fields as binary strings! (No collation) */ - if (no_sys) { - /* TRX_ID */ - if (i == trx_id_pos) { - continue; - } - - /* DB_ROLL_PTR */ - if (i == trx_id_pos + 1) { - continue; - } + if (no_sys && (i == index->db_trx_id() + || i == index->db_roll_ptr())) { + continue; } if (!dfield_is_ext(dfield) @@ -1200,7 +1126,7 @@ of the column and must not be poisoned with the new values. @param[in] data 'internally' stored part of the field containing also the reference to the external part @param[in] local_len length of data, in bytes -@param[in] page_size BLOB page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] len input - length of prefix to fetch; output: fetched length of the prefix @param[in,out] heap heap where to allocate @@ -1210,14 +1136,14 @@ byte* row_upd_ext_fetch( const byte* data, ulint local_len, - const page_size_t& page_size, + ulint zip_size, ulint* len, mem_heap_t* heap) { byte* buf = static_cast<byte*>(mem_heap_alloc(heap, *len)); *len = btr_copy_externally_stored_field_prefix( - buf, *len, page_size, data, local_len); + buf, *len, zip_size, data, local_len); /* We should never update records containing a half-deleted BLOB. */ ut_a(*len); @@ -1233,7 +1159,7 @@ the given index entry field. @param[in] uf update field @param[in,out] heap memory heap for allocating and copying the new value -@param[in] page_size page size */ +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 */ static void row_upd_index_replace_new_col_val( @@ -1242,7 +1168,7 @@ row_upd_index_replace_new_col_val( const dict_col_t* col, const upd_field_t* uf, mem_heap_t* heap, - const page_size_t& page_size) + ulint zip_size) { ulint len; const byte* data; @@ -1256,7 +1182,7 @@ row_upd_index_replace_new_col_val( len = dfield_get_len(dfield); data = static_cast<const byte*>(dfield_get_data(dfield)); - if (field->prefix_len > 0) { + if (field && field->prefix_len > 0) { ibool fetch_ext = dfield_is_ext(dfield) && len < (ulint) field->prefix_len + BTR_EXTERN_FIELD_REF_SIZE; @@ -1266,7 +1192,7 @@ row_upd_index_replace_new_col_val( len = field->prefix_len; - data = row_upd_ext_fetch(data, l, page_size, + data = row_upd_ext_fetch(data, l, zip_size, &len, heap); } @@ -1322,6 +1248,57 @@ row_upd_index_replace_new_col_val( } } +/** Apply an update vector to an metadata entry. +@param[in,out] entry clustered index metadata record to be updated +@param[in] index index of the entry +@param[in] update update vector built for the entry +@param[in,out] heap memory heap for copying off-page columns */ +static +void +row_upd_index_replace_metadata( + dtuple_t* entry, + const dict_index_t* index, + const upd_t* update, + mem_heap_t* heap) +{ + ut_ad(!index->table->skip_alter_undo); + ut_ad(update->is_alter_metadata()); + ut_ad(entry->info_bits == update->info_bits); + ut_ad(entry->n_fields == ulint(index->n_fields) + 1); + const ulint zip_size = index->table->space->zip_size(); + const ulint first = index->first_user_field(); + ut_d(bool found_mblob = false); + + for (ulint i = upd_get_n_fields(update); i--; ) { + const upd_field_t* uf = upd_get_nth_field(update, i); + ut_ad(!upd_fld_is_virtual_col(uf)); + ut_ad(uf->field_no >= first - 2); + ulint f = uf->field_no; + dfield_t* dfield = dtuple_get_nth_field(entry, f); + + if (f == first) { + ut_d(found_mblob = true); + ut_ad(!dfield_is_null(&uf->new_val)); + ut_ad(dfield_is_ext(dfield)); + ut_ad(dfield_get_len(dfield) == FIELD_REF_SIZE); + ut_ad(!dfield_is_null(dfield)); + dfield_set_data(dfield, uf->new_val.data, + uf->new_val.len); + if (dfield_is_ext(&uf->new_val)) { + dfield_set_ext(dfield); + } + continue; + } + + f -= f > first; + const dict_field_t* field = dict_index_get_nth_field(index, f); + row_upd_index_replace_new_col_val(dfield, field, field->col, + uf, heap, zip_size); + } + + ut_ad(found_mblob); +} + /** Apply an update vector to an index entry. @param[in,out] entry index entry to be updated; the clustered index record must be covered by a lock or a page latch to prevent @@ -1337,8 +1314,14 @@ row_upd_index_replace_new_col_vals_index_pos( mem_heap_t* heap) { ut_ad(!index->table->skip_alter_undo); + ut_ad(!entry->is_metadata() || entry->info_bits == update->info_bits); + + if (UNIV_UNLIKELY(entry->is_alter_metadata())) { + row_upd_index_replace_metadata(entry, index, update, heap); + return; + } - const page_size_t& page_size = dict_table_page_size(index->table); + const ulint zip_size = index->table->space->zip_size(); dtuple_set_info_bits(entry, update->info_bits); @@ -1364,7 +1347,7 @@ row_upd_index_replace_new_col_vals_index_pos( if (uf) { row_upd_index_replace_new_col_val( dtuple_get_nth_field(entry, i), - field, col, uf, heap, page_size); + field, col, uf, heap, zip_size); } } } @@ -1390,7 +1373,7 @@ row_upd_index_replace_new_col_vals( ulint i; const dict_index_t* clust_index = dict_table_get_first_index(index->table); - const page_size_t& page_size = dict_table_page_size(index->table); + const ulint zip_size = index->table->space->zip_size(); ut_ad(!index->table->skip_alter_undo); @@ -1420,7 +1403,7 @@ row_upd_index_replace_new_col_vals( if (uf) { row_upd_index_replace_new_col_val( dtuple_get_nth_field(entry, i), - field, col, uf, heap, page_size); + field, col, uf, heap, zip_size); } } } @@ -1644,8 +1627,7 @@ row_upd_replace( } if (n_ext_cols) { - *ext = row_ext_create(n_ext_cols, ext_cols, table->flags, row, - heap); + *ext = row_ext_create(n_ext_cols, ext_cols, *table, row, heap); } else { *ext = NULL; } @@ -1753,11 +1735,9 @@ row_upd_changes_ord_field_binary_func( mem_heap_t* temp_heap = NULL; const dfield_t* new_field = &upd_field->new_val; - const page_size_t page_size - = (ext != NULL) - ? ext->page_size - : dict_table_page_size( - index->table); + const ulint zip_size = ext + ? ext->zip_size + : index->table->space->zip_size(); ut_ad(dfield->data != NULL && dfield->len > GEO_DATA_HEADER_SIZE); @@ -1774,7 +1754,7 @@ row_upd_changes_ord_field_binary_func( dptr = btr_copy_externally_stored_field( &dlen, dptr, - page_size, + zip_size, flen, temp_heap); } else { @@ -1837,7 +1817,7 @@ row_upd_changes_ord_field_binary_func( dptr = btr_copy_externally_stored_field( &dlen, dptr, - page_size, + zip_size, flen, temp_heap); } else { @@ -2442,7 +2422,7 @@ row_upd_sec_index_entry( #ifdef UNIV_DEBUG mtr_commit(&mtr); mtr_start(&mtr); - ut_ad(btr_validate_index(index, 0, false)); + ut_ad(btr_validate_index(index, 0)); ut_ad(0); #endif /* UNIV_DEBUG */ break; @@ -2478,7 +2458,7 @@ row_upd_sec_index_entry( err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; @@ -2563,10 +2543,10 @@ row_upd_sec_step( } #ifdef UNIV_DEBUG -# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \ - row_upd_clust_rec_by_insert_inherit_func(rec,offsets,entry,update) +# define row_upd_clust_rec_by_insert_inherit(rec,index,offsets,entry,update) \ + row_upd_clust_rec_by_insert_inherit_func(rec,index,offsets,entry,update) #else /* UNIV_DEBUG */ -# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \ +# define row_upd_clust_rec_by_insert_inherit(rec,index,offsets,entry,update) \ row_upd_clust_rec_by_insert_inherit_func(rec,entry,update) #endif /* UNIV_DEBUG */ /*******************************************************************//** @@ -2581,6 +2561,7 @@ row_upd_clust_rec_by_insert_inherit_func( /*=====================================*/ const rec_t* rec, /*!< in: old record, or NULL */ #ifdef UNIV_DEBUG + dict_index_t* index, /*!< in: index, or NULL */ const ulint* offsets,/*!< in: rec_get_offsets(rec), or NULL */ #endif /* UNIV_DEBUG */ dtuple_t* entry, /*!< in/out: updated entry to be @@ -2591,6 +2572,8 @@ row_upd_clust_rec_by_insert_inherit_func( ulint i; ut_ad(!rec == !offsets); + ut_ad(!rec == !index); + ut_ad(!rec || rec_offs_validate(rec, index, offsets)); ut_ad(!rec || rec_offs_any_extern(offsets)); for (i = 0; i < dtuple_get_n_fields(entry); i++) { @@ -2601,6 +2584,9 @@ row_upd_clust_rec_by_insert_inherit_func( ut_ad(!offsets || !rec_offs_nth_extern(offsets, i) == !dfield_is_ext(dfield) + || (!dict_index_get_nth_field(index, i)->name + && !dfield_is_ext(dfield) + && (dfield_is_null(dfield) || dfield->len == 0)) || upd_get_field_by_field_no(update, i, false)); if (!dfield_is_ext(dfield) || upd_get_field_by_field_no(update, i, false)) { @@ -2698,7 +2684,11 @@ row_upd_clust_rec_by_insert( if (index->is_instant()) entry->trim(*index); ut_ad(dtuple_get_info_bits(entry) == 0); - row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id); + { + dfield_t* t = dtuple_get_nth_field(entry, index->db_trx_id()); + ut_ad(t->len == DATA_TRX_ID_LEN); + trx_write_trx_id(static_cast<byte*>(t->data), trx->id); + } switch (node->state) { default: @@ -2707,7 +2697,7 @@ row_upd_clust_rec_by_insert( /* A lock wait occurred in row_ins_clust_index_entry() in the previous invocation of this function. */ row_upd_clust_rec_by_insert_inherit( - NULL, NULL, entry, node->update); + NULL, NULL, NULL, entry, node->update); break; case UPD_NODE_UPDATE_CLUSTERED: /* This is the first invocation of the function where @@ -2748,7 +2738,8 @@ err_exit: if (rec_offs_any_extern(offsets)) { if (row_upd_clust_rec_by_insert_inherit( - rec, offsets, entry, node->update)) { + rec, index, offsets, + entry, node->update)) { /* The blobs are disowned here, expecting the insert down below to inherit them. But if the insert fails, then this disown will be undone @@ -2781,7 +2772,7 @@ check_fk: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; @@ -3008,7 +2999,7 @@ row_upd_del_mark_clust_rec( err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; |