diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 96ba524fd8d..5122cbd47dd 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -3540,7 +3540,7 @@ dberr_t btr_cur_optimistic_update(ulint flags, btr_cur_t *cursor, trx_is_recv(thr_get_trx(thr))); #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ - if (!row_upd_changes_field_size_or_external(index, *offsets, update)) { + if (!row_upd_changes_field_size_or_external(index, *offsets, update, rec)) { /* The simplest and the most common case: the update does not change the size of any field and none of the updated fields is externally stored in rec or update, and there is enough space diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index c43c468d998..ce1da9e779a 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -3579,7 +3579,7 @@ static void ibuf_insert_to_index_page( /* We cannot invoke btr_cur_optimistic_update() here, because we do not have a btr_cur_t or que_thr_t, as the insert buffer merge occurs at a very low level. */ - if (!row_upd_changes_field_size_or_external(index, offsets, update) && + if (!row_upd_changes_field_size_or_external(index, offsets, update, rec) && (!page_zip || btr_cur_update_alloc_zip(page_zip, &page_cur, index, offsets, rec_offs_size(offsets), false, mtr))) { diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index 48457d3e462..c4b47e23283 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -153,7 +153,8 @@ void row_upd_index_write_log(dict_index_t *index, const upd_t *update, bool row_upd_changes_field_size_or_external( const dict_index_t *index, /*!< in: index */ const ulint *offsets, /*!< in: rec_get_offsets(rec, index) */ - const upd_t *update); /*!< in: update vector */ + const upd_t *update, /*!< in: update vector */ + const rec_t *rec); /** Returns true if row update contains disowned external fields. @return true if the update contains disowned external fields. */ [[nodiscard]] bool row_upd_changes_disowned_external( diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 814e89d2716..ab8acb1d639 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1943,7 +1943,7 @@ static dberr_t row_update_inplace_for_intrinsic(const upd_node_t *node) { ut_ad(pcur.get_block()->made_dirty_with_no_latch); bool size_changes = - row_upd_changes_field_size_or_external(index, offsets, node->update); + row_upd_changes_field_size_or_external(index, offsets, node->update, rec); if (size_changes) { mtr_commit(&mtr); diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 27eec2828e4..90245b73576 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -358,7 +358,8 @@ void row_upd_index_entry_sys_field(dtuple_t *entry, dict_index_t *index, bool row_upd_changes_field_size_or_external( const dict_index_t *index, /*!< in: index */ const ulint *offsets, /*!< in: rec_get_offsets(rec, index) */ - const upd_t *update) /*!< in: update vector */ + const upd_t *update, /*!< in: update vector */ + const rec_t *rec) { const upd_field_t *upd_field; const dfield_t *new_val; @@ -421,6 +422,19 @@ bool row_upd_changes_field_size_or_external( not inlined default value, do it in pessimistic way */ if (rec_offs_nth_default(index, offsets, field_no)) { old_len = UNIV_SQL_ADD_COL_DEFAULT; + } else if (rec_offs_nth_sql_null(index, offsets, field_no) && + index->has_instant_cols_or_row_versions()) { + uint16_t real_field_no = field_no; + if (index->has_row_versions()) { + uint8_t version = UINT8_UNDEFINED; + if (rec_old_is_versioned(rec)) { + version = rec_get_instant_row_version_old(rec); + } + real_field_no = index->get_field_phy_pos(field_no, version); + } + if (real_field_no >= rec_get_n_fields_old_raw(rec)) { + old_len = UNIV_SQL_NULL; + } } } diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 328fc8dfacf..9a4ba839ccb 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -2532,7 +2532,7 @@ bool trx_undo_prev_version_build( type_cmpl); ut_a(ptr); - if (row_upd_changes_field_size_or_external(index, offsets, update)) { + if (row_upd_changes_field_size_or_external(index, offsets, update, rec)) { /* We should confirm the existence of disowned external data, if the previous version record is delete marked. If the trx_id of the previous record is seen by purge view, we should treat