diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-01-17 10:46:33 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-01-17 14:27:28 +0200 |
commit | 5838b52743423a2f9cf8d1a80e21c502cd308604 (patch) | |
tree | 71b39661345098211d3dff70c83f2305ea58ddc4 /storage/innobase/btr/btr0cur.cc | |
parent | 3e38d15585f03e794a83a1d141ead33e8c878f27 (diff) | |
download | mariadb-git-5838b52743423a2f9cf8d1a80e21c502cd308604.tar.gz |
MDEV-21511 Wrong estimate of affected BLOB columns in update
During update, rollback, or MVCC read, we may miscalculate
the number of off-page columns, and thus the size of the
clustered index record. The function btr_push_update_extern_fields()
is mostly redundant, because the off-page columns would also be
moved by row_upd_index_replace_new_col_val(), which is invoked
via row_upd_index_replace_new_col_vals().
btr_push_update_extern_fields(): Remove.
This is based on
mysql/mysql-server@1fa475b85d24de4b9ce2958c0eed738c221fc82c
which refines a fix for a recovery bug fix
mysql/mysql-server@ce0a1e85e24e48b8171f767b44330da635a6ea0a
in MySQL 5.7.5.
No test case was provided by Oracle.
Some of the changed code is being covered by the existing test
innodb.blob-crash.
Diffstat (limited to 'storage/innobase/btr/btr0cur.cc')
-rw-r--r-- | storage/innobase/btr/btr0cur.cc | 86 |
1 files changed, 5 insertions, 81 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 97e7e3d47a2..72f061f2a5f 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -1,9 +1,9 @@ /***************************************************************************** -Copyright (c) 1994, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2015, 2019, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -4374,7 +4374,9 @@ btr_cur_pessimistic_update( ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec)); ut_ad(rec_offs_validate(rec, index, *offsets)); - n_ext += btr_push_update_extern_fields(new_entry, update, entry_heap); + + /* Get number of externally stored columns in updated record */ + n_ext = dtuple_get_n_ext(new_entry); if ((flags & BTR_NO_UNDO_LOG_FLAG) && rec_offs_any_extern(*offsets)) { @@ -6594,84 +6596,6 @@ btr_cur_unmark_extern_fields( } /*******************************************************************//** -Flags the data tuple fields that are marked as extern storage in the -update vector. We use this function to remember which fields we must -mark as extern storage in a record inserted for an update. -@return number of flagged external columns */ -ulint -btr_push_update_extern_fields( -/*==========================*/ - dtuple_t* tuple, /*!< in/out: data tuple */ - const upd_t* update, /*!< in: update vector */ - mem_heap_t* heap) /*!< in: memory heap */ -{ - ulint n_pushed = 0; - ulint n; - const upd_field_t* uf; - - uf = update->fields; - n = upd_get_n_fields(update); - - for (; n--; uf++) { - if (dfield_is_ext(&uf->new_val)) { - dfield_t* field - = dtuple_get_nth_field(tuple, uf->field_no); - - if (!dfield_is_ext(field)) { - dfield_set_ext(field); - n_pushed++; - } - - switch (uf->orig_len) { - byte* data; - ulint len; - byte* buf; - case 0: - break; - case BTR_EXTERN_FIELD_REF_SIZE: - /* Restore the original locally stored - part of the column. In the undo log, - InnoDB writes a longer prefix of externally - stored columns, so that column prefixes - in secondary indexes can be reconstructed. */ - dfield_set_data(field, - (byte*) dfield_get_data(field) - + dfield_get_len(field) - - BTR_EXTERN_FIELD_REF_SIZE, - BTR_EXTERN_FIELD_REF_SIZE); - dfield_set_ext(field); - break; - default: - /* Reconstruct the original locally - stored part of the column. The data - will have to be copied. */ - ut_a(uf->orig_len > BTR_EXTERN_FIELD_REF_SIZE); - - data = (byte*) dfield_get_data(field); - len = dfield_get_len(field); - - buf = (byte*) mem_heap_alloc(heap, - uf->orig_len); - /* Copy the locally stored prefix. */ - memcpy(buf, data, - uf->orig_len - - BTR_EXTERN_FIELD_REF_SIZE); - /* Copy the BLOB pointer. */ - memcpy(buf + uf->orig_len - - BTR_EXTERN_FIELD_REF_SIZE, - data + len - BTR_EXTERN_FIELD_REF_SIZE, - BTR_EXTERN_FIELD_REF_SIZE); - - dfield_set_data(field, buf, uf->orig_len); - dfield_set_ext(field); - } - } - } - - return(n_pushed); -} - -/*******************************************************************//** Returns the length of a BLOB part stored on the header page. @return part length */ static |