Skip to content

Commit e6248f5

Browse files
committed
Bug#36526369 MySQL server crashes on UPDATE after ALTER TABLE
Issue: In bug#35183686 fix, we started logging the fields whose column order changed. But while calculating size needed in redo to log index information these columns were missing from calculation. Fix Make sure these colums are also considered while calculating size needed to log index entry. Change-Id: Ic8752c72a8f5beddfc5739688068b9c32b02a700
1 parent 71ae8c6 commit e6248f5

File tree

1 file changed

+39
-26
lines changed

1 file changed

+39
-26
lines changed

storage/innobase/mtr/mtr0log.cc

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -515,12 +515,15 @@ constexpr size_t inst_col_info_size = 6;
515515
@param[in] is_comp true if COMP
516516
@param[in] is_versioned if table has row versions
517517
@param[in] is_instant true if table has INSTANT cols
518+
@param[in] fields_with_changed_order bitmap to indicate fields with changed
519+
order
518520
@param[out] size_needed total size needed on REDO LOG */
519521
static void log_index_get_size_needed(const dict_index_t *index, size_t size,
520522
uint16_t n, bool is_comp,
521523
bool is_versioned, bool is_instant,
524+
const bool *fields_with_changed_order,
522525
size_t &size_needed) {
523-
auto size_for_versioned_fields = [](const dict_index_t *ind) {
526+
auto size_for_versioned_fields = [&](const dict_index_t *ind) {
524527
size_t _size = 0;
525528
/* 2 bytes for number of columns with version */
526529
_size += 2;
@@ -530,6 +533,16 @@ static void log_index_get_size_needed(const dict_index_t *index, size_t size,
530533
ut_ad(n_versioned_fields != 0);
531534

532535
_size += n_versioned_fields * inst_col_info_size;
536+
537+
/* For fields with changed order */
538+
size_t n_changed_order_fields = 0;
539+
for (size_t i = 0; i < n; i++) {
540+
if (fields_with_changed_order[i]) {
541+
n_changed_order_fields++;
542+
}
543+
}
544+
_size += n_changed_order_fields * inst_col_info_size;
545+
533546
return (_size);
534547
};
535548

@@ -799,9 +812,33 @@ bool mlog_open_and_write_index(mtr_t *mtr, const byte *rec,
799812
n = DICT_INDEX_SPATIAL_NODEPTR_SIZE;
800813
}
801814

815+
/* Ordinal position of an existing field can't be changed with INSTANT
816+
algorithm. But when it is combined with ADD/DROP COLUMN, ordinal position
817+
of a filed can be changed. This bool array of size #fields in index,
818+
represents if ordinal position of an existing filed is changed. */
819+
bool *fields_with_changed_order = nullptr;
820+
if (is_versioned) {
821+
fields_with_changed_order = new bool[n];
822+
memset(fields_with_changed_order, false, (sizeof(bool) * n));
823+
824+
uint16_t phy_pos = 0;
825+
for (size_t i = 0; i < n; i++) {
826+
dict_field_t *field = index->get_field(i);
827+
const dict_col_t *col = field->col;
828+
829+
if (col->is_instant_added() || col->is_instant_dropped()) {
830+
continue;
831+
} else if (field->get_phy_pos() >= phy_pos) {
832+
phy_pos = field->get_phy_pos();
833+
} else {
834+
fields_with_changed_order[i] = true;
835+
}
836+
}
837+
}
838+
802839
size_t size_needed = 0;
803840
log_index_get_size_needed(index, size, n, is_comp, is_versioned, is_instant,
804-
size_needed);
841+
fields_with_changed_order, size_needed);
805842
size_t total = size_needed;
806843
size_t alloc = total;
807844
if (alloc > mtr_buf_t::MAX_DATA_SIZE) {
@@ -846,30 +883,6 @@ bool mlog_open_and_write_index(mtr_t *mtr, const byte *rec,
846883
return true;
847884
};
848885

849-
/* Ordinal position of an existing field can't be changed with INSTANT
850-
algorithm. But when it is combined with ADD/DROP COLUMN, ordinal position
851-
of a filed can be changed. This bool array of size #fields in index,
852-
represents if ordinal position of an existing filed is changed. */
853-
bool *fields_with_changed_order = nullptr;
854-
if (is_versioned) {
855-
fields_with_changed_order = new bool[n];
856-
memset(fields_with_changed_order, false, (sizeof(bool) * n));
857-
858-
uint16_t phy_pos = 0;
859-
for (size_t i = 0; i < n; i++) {
860-
dict_field_t *field = index->get_field(i);
861-
const dict_col_t *col = field->col;
862-
863-
if (col->is_instant_added() || col->is_instant_dropped()) {
864-
continue;
865-
} else if (field->get_phy_pos() >= phy_pos) {
866-
phy_pos = field->get_phy_pos();
867-
} else {
868-
fields_with_changed_order[i] = true;
869-
}
870-
}
871-
}
872-
873886
if (is_comp) {
874887
/* Write fields info. */
875888
if (!log_index_fields(index, n, is_versioned, instant_fields_to_log,

0 commit comments

Comments
 (0)